mirror of
				https://github.com/isar/rusqlite.git
				synced 2025-10-31 22:08:55 +08:00 
			
		
		
		
	Handle raw string literal
This commit is contained in:
		| @@ -14,3 +14,4 @@ proc-macro = true | |||||||
| [dependencies] | [dependencies] | ||||||
| sqlite3-parser = { version = "0.12", default-features = false, features = ["YYNOERRORRECOVERY"] } | sqlite3-parser = { version = "0.12", default-features = false, features = ["YYNOERRORRECOVERY"] } | ||||||
| fallible-iterator = "0.3" | fallible-iterator = "0.3" | ||||||
|  | litrs = { version = "0.4", default-features = false } | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| //! Private implementation details of `rusqlite`. | //! Private implementation details of `rusqlite`. | ||||||
|  |  | ||||||
| use proc_macro::{Delimiter, Group, Literal, Span, TokenStream, TokenTree}; | use litrs::StringLit; | ||||||
|  | use proc_macro::{Group, Span, TokenStream, TokenTree}; | ||||||
|  |  | ||||||
| use fallible_iterator::FallibleIterator; | use fallible_iterator::FallibleIterator; | ||||||
| use sqlite3_parser::ast::{ParameterInfo, ToTokens}; | use sqlite3_parser::ast::{ParameterInfo, ToTokens}; | ||||||
| @@ -25,15 +26,12 @@ fn try_bind(input: TokenStream) -> Result<TokenStream> { | |||||||
|         (stmt, literal) |         (stmt, literal) | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     let literal = match into_literal(&literal) { |     let call_site = literal.span(); | ||||||
|         Some(it) => it, |     let string_lit = match StringLit::try_from(literal) { | ||||||
|         None => return Err("expected a plain string literal".to_string()), |         Ok(string_lit) => string_lit, | ||||||
|  |         Err(e) => return Ok(e.to_compile_error()), | ||||||
|     }; |     }; | ||||||
|     let sql = literal.to_string(); |     let sql = string_lit.value(); | ||||||
|     if !sql.starts_with('"') { |  | ||||||
|         return Err("expected a plain string literal".to_string()); |  | ||||||
|     } |  | ||||||
|     let sql = strip_matches(&sql, "\""); |  | ||||||
|  |  | ||||||
|     let mut parser = Parser::new(sql.as_bytes()); |     let mut parser = Parser::new(sql.as_bytes()); | ||||||
|     let ast = match parser.next() { |     let ast = match parser.next() { | ||||||
| @@ -54,7 +52,6 @@ fn try_bind(input: TokenStream) -> Result<TokenStream> { | |||||||
|         return Err("Mixing named and numbered parameters is not supported.".to_string()); |         return Err("Mixing named and numbered parameters is not supported.".to_string()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     let call_site = literal.span(); |  | ||||||
|     let mut res = TokenStream::new(); |     let mut res = TokenStream::new(); | ||||||
|     for (i, name) in info.names.iter().enumerate() { |     for (i, name) in info.names.iter().enumerate() { | ||||||
|         res.extend(Some(stmt.clone())); |         res.extend(Some(stmt.clone())); | ||||||
| @@ -71,27 +68,6 @@ fn try_bind(input: TokenStream) -> Result<TokenStream> { | |||||||
|     Ok(res) |     Ok(res) | ||||||
| } | } | ||||||
|  |  | ||||||
| fn into_literal(ts: &TokenTree) -> Option<Literal> { |  | ||||||
|     match ts { |  | ||||||
|         TokenTree::Literal(l) => Some(l.clone()), |  | ||||||
|         TokenTree::Group(g) => match g.delimiter() { |  | ||||||
|             Delimiter::None => match g.stream().into_iter().collect::<Vec<_>>().as_slice() { |  | ||||||
|                 [TokenTree::Literal(l)] => Some(l.clone()), |  | ||||||
|                 _ => None, |  | ||||||
|             }, |  | ||||||
|             Delimiter::Parenthesis | Delimiter::Brace | Delimiter::Bracket => None, |  | ||||||
|         }, |  | ||||||
|         _ => None, |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| fn strip_matches<'a>(s: &'a str, pattern: &str) -> &'a str { |  | ||||||
|     s.strip_prefix(pattern) |  | ||||||
|         .unwrap_or(s) |  | ||||||
|         .strip_suffix(pattern) |  | ||||||
|         .unwrap_or(s) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| fn respan(ts: TokenStream, span: Span) -> TokenStream { | fn respan(ts: TokenStream, span: Span) -> TokenStream { | ||||||
|     let mut res = TokenStream::new(); |     let mut res = TokenStream::new(); | ||||||
|     for tt in ts { |     for tt in ts { | ||||||
|   | |||||||
| @@ -21,19 +21,19 @@ fn test_literal() -> Result { | |||||||
| } | } | ||||||
|  |  | ||||||
| #[test] | #[test] | ||||||
| fn test_no_placeholder() -> Result { | fn test_no_placeholder() { | ||||||
|     let _stmt = Stmt; |     let _stmt = Stmt; | ||||||
|     __bind!(_stmt "SELECT 1"); |     __bind!(_stmt "SELECT 1"); | ||||||
|     Ok(()) | } | ||||||
|  |  | ||||||
|  | #[test] | ||||||
|  | fn test_raw_string() { | ||||||
|  |     let _stmt = Stmt; | ||||||
|  |     __bind!(_stmt r"SELECT 1"); | ||||||
|  |     __bind!(_stmt r#"SELECT 1"#); | ||||||
| } | } | ||||||
|  |  | ||||||
| /* FIXME | /* FIXME | ||||||
| #[test] |  | ||||||
| fn test_raw_string() { |  | ||||||
|     let stmt = (); |  | ||||||
|     __bind!(stmt r#"SELECT 1"#); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #[test] | #[test] | ||||||
| fn test_const() { | fn test_const() { | ||||||
|     const SQL: &str = "SELECT 1"; |     const SQL: &str = "SELECT 1"; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user