enquote-1.1.0/.cargo_vcs_info.json0000644000000001120000000000100125050ustar { "git": { "sha1": "c64ca4c6128d25a88a70669cd5e9fe8dda4fe623" } } enquote-1.1.0/.gitignore000064400000000000000000000000360072674642500133220ustar 00000000000000/target **/*.rs.bk Cargo.lock enquote-1.1.0/Cargo.toml0000644000000016260000000000100105160ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "enquote" version = "1.1.0" authors = ["reujab "] description = "Quotes and unquotes strings" readme = "readme.md" keywords = ["quote", "enquote", "unquote"] categories = ["parser-implementations", "parsing", "value-formatting"] license = "Unlicense" repository = "https://github.com/reujab/enquote" [dependencies.thiserror] version = "1.0" enquote-1.1.0/Cargo.toml.orig000064400000000000000000000006020072674642500142200ustar 00000000000000[package] name = "enquote" version = "1.1.0" authors = ["reujab "] description = "Quotes and unquotes strings" repository = "https://github.com/reujab/enquote" readme = "readme.md" keywords = ["quote", "enquote", "unquote"] categories = ["parser-implementations", "parsing", "value-formatting"] license = "Unlicense" edition = "2018" [dependencies] thiserror = "1.0" enquote-1.1.0/readme.md000064400000000000000000000007550072674642500131210ustar 00000000000000# enquote [![crate](https://img.shields.io/crates/v/enquote.svg)](https://crates.io/crates/enquote) [![docs](https://docs.rs/enquote/badge.svg)](https://docs.rs/enquote) This Rust library quotes, unquotes, and unescapes strings. ## Example ```rust extern crate enquote; fn main() { assert_eq!(enquote::enquote('\'', "foo'bar"), "'foo\\'bar'"); assert_eq!(enquote::unquote("'foo\\'bar\\n'").unwrap(), "foo'bar\n"); assert_eq!(enquote::unescape("\\n", None).unwrap(), "\n"); } ``` enquote-1.1.0/src/error.rs000064400000000000000000000006570072674642500136310ustar 00000000000000use thiserror::Error; #[derive(Error, Debug, PartialEq)] pub enum Error { #[error("not enough chars")] NotEnoughChars, #[error("unrecognized quote character")] UnrecognizedQuote, #[error("unexpected eof")] UnexpectedEOF, #[error("illegal character")] IllegalChar, #[error("unrecognized escape sequence")] UnrecognizedEscape, #[error("invalid unicode code point")] InvalidUnicode, } enquote-1.1.0/src/lib.rs000064400000000000000000000075440072674642500132500ustar 00000000000000//! This Rust library quotes, unquotes, and unescapes strings. //! //! # Examples //! ``` //! extern crate enquote; //! //! fn main() { //! assert_eq!(enquote::enquote('\'', "foo'bar"), "'foo\\'bar'"); //! assert_eq!(enquote::unquote("'foo\\'bar\\n'").unwrap(), "foo'bar\n"); //! assert_eq!(enquote::unescape("\\n", None).unwrap(), "\n"); //! } //! ``` mod error; pub use error::Error; /// Enquotes `s` with `quote`. pub fn enquote(quote: char, s: &str) -> String { // escapes any `quote` in `s` let escaped = s .chars() .map(|c| match c { // escapes the character if it's the quote _ if c == quote => format!("\\{}", quote), // escapes backslashes '\\' => "\\\\".into(), // no escape required _ => c.to_string(), }) .collect::(); // enquotes escaped string quote.to_string() + &escaped + "e.to_string() } /// Unquotes `s`. pub fn unquote(s: &str) -> Result { if s.chars().count() < 2 { return Err(Error::NotEnoughChars); } let quote = s.chars().next().unwrap(); if quote != '"' && quote != '\'' && quote != '`' { return Err(Error::UnrecognizedQuote); } if s.chars().last().unwrap() != quote { return Err(Error::UnexpectedEOF); } // removes quote characters // the sanity checks performed above ensure that the quotes will be ASCII and this will not // panic let s = &s[1..s.len() - 1]; unescape(s, Some(quote)) } /// Returns `s` after processing escapes such as `\n` and `\x00`. pub fn unescape(s: &str, illegal: Option) -> Result { let mut chars = s.chars(); let mut unescaped = String::new(); loop { match chars.next() { None => break, Some(c) => unescaped.push(match c { _ if Some(c) == illegal => return Err(Error::IllegalChar), '\\' => match chars.next() { None => return Err(Error::UnexpectedEOF), Some(c) => match c { _ if c == '\\' || c == '"' || c == '\'' || c == '`' => c, 'a' => '\x07', 'b' => '\x08', 'f' => '\x0c', 'n' => '\n', 'r' => '\r', 't' => '\t', 'v' => '\x0b', // octal '0'..='9' => { let octal = c.to_string() + &take(&mut chars, 2); u8::from_str_radix(&octal, 8).map_err(|_| Error::UnrecognizedEscape)? as char } // hex 'x' => { let hex = take(&mut chars, 2); u8::from_str_radix(&hex, 16).map_err(|_| Error::UnrecognizedEscape)? as char } // unicode 'u' => decode_unicode(&take(&mut chars, 4))?, 'U' => decode_unicode(&take(&mut chars, 8))?, _ => return Err(Error::UnrecognizedEscape), }, }, _ => c, }), } } Ok(unescaped) } #[inline] // Iterator#take cannot be used because it consumes the iterator fn take>(iterator: &mut I, n: usize) -> String { let mut s = String::with_capacity(n); for _ in 0..n { s.push(iterator.next().unwrap_or_default()); } s } fn decode_unicode(code_point: &str) -> Result { match u32::from_str_radix(code_point, 16) { Err(_) => return Err(Error::UnrecognizedEscape), Ok(n) => std::char::from_u32(n).ok_or(Error::InvalidUnicode), } } enquote-1.1.0/tests/lib.rs000064400000000000000000000045600072674642500136160ustar 00000000000000extern crate enquote; #[test] fn enquote() { assert_eq!( enquote::enquote('"', r#""Fran & Freddie's Diner ☺\""#), r#""\"Fran & Freddie's Diner ☺\\\"""#, ); assert_eq!(enquote::enquote('"', ""), r#""""#); assert_eq!(enquote::enquote('"', r#"""#), r#""\"""#); assert_eq!( enquote::enquote('\'', r#""Fran & Freddie's Diner ☺\""#), r#"'"Fran & Freddie\'s Diner ☺\\"'"#, ); assert_eq!(enquote::enquote('\'', ""), "''"); assert_eq!(enquote::enquote('\'', "'"), r#"'\''"#); assert_eq!(enquote::enquote('`', ""), "``"); assert_eq!(enquote::enquote('`', "`"), r#"`\``"#); } #[test] fn unquote() { assert_eq!( enquote::unquote("").unwrap_err(), enquote::Error::NotEnoughChars, ); assert_eq!( enquote::unquote("foobar").unwrap_err(), enquote::Error::UnrecognizedQuote, ); assert_eq!( enquote::unquote("'foobar").unwrap_err(), enquote::Error::UnexpectedEOF, ); assert_eq!( enquote::unquote("'foo'bar'").unwrap_err(), enquote::Error::IllegalChar, ); assert_eq!( enquote::unquote("'foobar\\'").unwrap_err(), enquote::Error::UnexpectedEOF, ); assert_eq!( enquote::unquote("'\\q'").unwrap_err(), enquote::Error::UnrecognizedEscape, ); assert_eq!( enquote::unquote("'\\00'").unwrap_err(), enquote::Error::UnrecognizedEscape, ); assert_eq!( enquote::unquote(r#""\"Fran & Freddie's Diner ☺\\\"""#).unwrap(), r#""Fran & Freddie's Diner ☺\""#, ); assert_eq!(enquote::unquote(r#""""#).unwrap(), ""); assert_eq!(enquote::unquote(r#""\"""#).unwrap(), r#"""#); assert_eq!( enquote::unquote(r#"'"Fran & Freddie\'s Diner ☺\\"'"#).unwrap(), r#""Fran & Freddie's Diner ☺\""#, ); assert_eq!(enquote::unquote("''").unwrap(), ""); assert_eq!(enquote::unquote(r#"'\''"#).unwrap(), "'"); assert_eq!(enquote::unquote("``").unwrap(), ""); assert_eq!(enquote::unquote(r#"`\``"#).unwrap(), "`"); assert_eq!(enquote::unquote("'\\n'").unwrap(), "\n"); assert_eq!(enquote::unquote("'\\101'").unwrap(), "A"); assert_eq!(enquote::unquote("'\\x76'").unwrap(), "\x76"); assert_eq!(enquote::unquote("'\\u2714'").unwrap(), "\u{2714}"); assert_eq!(enquote::unquote("'\\U0001f427'").unwrap(), "\u{1f427}"); } enquote-1.1.0/unlicense000064400000000000000000000022730072674642500132470ustar 00000000000000This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to