]> git.lizzy.rs Git - rust.git/blob - crates/proc_macro_srv/src/rustc_server.rs
Merge #6783
[rust.git] / crates / proc_macro_srv / src / rustc_server.rs
1 //! Rustc proc-macro server implementation with tt
2 //!
3 //! Based on idea from https://github.com/fedochet/rust-proc-macro-expander
4 //! The lib-proc-macro server backend is `TokenStream`-agnostic, such that
5 //! we could provide any TokenStream implementation.
6 //! The original idea from fedochet is using proc-macro2 as backend,
7 //! we use tt instead for better intergation with RA.
8 //!
9 //! FIXME: No span and source file information is implemented yet
10
11 use crate::proc_macro::bridge::{self, server};
12
13 use std::collections::{Bound, HashMap};
14 use std::hash::Hash;
15 use std::iter::FromIterator;
16 use std::str::FromStr;
17 use std::{ascii, vec::IntoIter};
18
19 type Group = tt::Subtree;
20 type TokenTree = tt::TokenTree;
21 type Punct = tt::Punct;
22 type Spacing = tt::Spacing;
23 type Literal = tt::Literal;
24 type Span = tt::TokenId;
25
26 #[derive(Debug, Clone)]
27 pub struct TokenStream {
28     pub subtree: tt::Subtree,
29 }
30
31 impl TokenStream {
32     pub fn new() -> Self {
33         TokenStream { subtree: Default::default() }
34     }
35
36     pub fn with_subtree(subtree: tt::Subtree) -> Self {
37         TokenStream { subtree }
38     }
39
40     pub fn is_empty(&self) -> bool {
41         self.subtree.token_trees.is_empty()
42     }
43 }
44
45 /// Creates a token stream containing a single token tree.
46 impl From<TokenTree> for TokenStream {
47     fn from(tree: TokenTree) -> TokenStream {
48         TokenStream { subtree: tt::Subtree { delimiter: None, token_trees: vec![tree] } }
49     }
50 }
51
52 /// Collects a number of token trees into a single stream.
53 impl FromIterator<TokenTree> for TokenStream {
54     fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
55         trees.into_iter().map(TokenStream::from).collect()
56     }
57 }
58
59 /// A "flattening" operation on token streams, collects token trees
60 /// from multiple token streams into a single stream.
61 impl FromIterator<TokenStream> for TokenStream {
62     fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
63         let mut builder = TokenStreamBuilder::new();
64         streams.into_iter().for_each(|stream| builder.push(stream));
65         builder.build()
66     }
67 }
68
69 impl Extend<TokenTree> for TokenStream {
70     fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) {
71         self.extend(trees.into_iter().map(TokenStream::from));
72     }
73 }
74
75 impl Extend<TokenStream> for TokenStream {
76     fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
77         for item in streams {
78             for tkn in item {
79                 match tkn {
80                     tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => {
81                         self.subtree.token_trees.extend(subtree.token_trees);
82                     }
83                     _ => {
84                         self.subtree.token_trees.push(tkn);
85                     }
86                 }
87             }
88         }
89     }
90 }
91
92 type Level = crate::proc_macro::Level;
93 type LineColumn = crate::proc_macro::LineColumn;
94 type SourceFile = crate::proc_macro::SourceFile;
95
96 /// A structure representing a diagnostic message and associated children
97 /// messages.
98 #[derive(Clone, Debug)]
99 pub struct Diagnostic {
100     level: Level,
101     message: String,
102     spans: Vec<Span>,
103     children: Vec<Diagnostic>,
104 }
105
106 impl Diagnostic {
107     /// Creates a new diagnostic with the given `level` and `message`.
108     pub fn new<T: Into<String>>(level: Level, message: T) -> Diagnostic {
109         Diagnostic { level, message: message.into(), spans: vec![], children: vec![] }
110     }
111 }
112
113 // Rustc Server Ident has to be `Copyable`
114 // We use a stub here for bypassing
115 #[derive(Hash, Eq, PartialEq, Copy, Clone)]
116 pub struct IdentId(u32);
117
118 #[derive(Clone, Hash, Eq, PartialEq)]
119 struct IdentData(tt::Ident);
120
121 #[derive(Default)]
122 struct IdentInterner {
123     idents: HashMap<IdentData, u32>,
124     ident_data: Vec<IdentData>,
125 }
126
127 impl IdentInterner {
128     fn intern(&mut self, data: &IdentData) -> u32 {
129         if let Some(index) = self.idents.get(data) {
130             return *index;
131         }
132
133         let index = self.idents.len() as u32;
134         self.ident_data.push(data.clone());
135         self.idents.insert(data.clone(), index);
136         index
137     }
138
139     fn get(&self, index: u32) -> &IdentData {
140         &self.ident_data[index as usize]
141     }
142
143     #[allow(unused)]
144     fn get_mut(&mut self, index: u32) -> &mut IdentData {
145         self.ident_data.get_mut(index as usize).expect("Should be consistent")
146     }
147 }
148
149 pub struct TokenStreamBuilder {
150     acc: TokenStream,
151 }
152
153 /// Public implementation details for the `TokenStream` type, such as iterators.
154 pub mod token_stream {
155     use std::str::FromStr;
156
157     use super::{TokenStream, TokenTree};
158
159     /// An iterator over `TokenStream`'s `TokenTree`s.
160     /// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups,
161     /// and returns whole groups as token trees.
162     impl IntoIterator for TokenStream {
163         type Item = TokenTree;
164         type IntoIter = super::IntoIter<TokenTree>;
165
166         fn into_iter(self) -> Self::IntoIter {
167             self.subtree.token_trees.into_iter()
168         }
169     }
170
171     type LexError = String;
172
173     /// Attempts to break the string into tokens and parse those tokens into a token stream.
174     /// May fail for a number of reasons, for example, if the string contains unbalanced delimiters
175     /// or characters not existing in the language.
176     /// All tokens in the parsed stream get `Span::call_site()` spans.
177     ///
178     /// NOTE: some errors may cause panics instead of returning `LexError`. We reserve the right to
179     /// change these errors into `LexError`s later.
180     impl FromStr for TokenStream {
181         type Err = LexError;
182
183         fn from_str(src: &str) -> Result<TokenStream, LexError> {
184             let (subtree, _token_map) =
185                 mbe::parse_to_token_tree(src).ok_or("Failed to parse from mbe")?;
186
187             Ok(TokenStream { subtree })
188         }
189     }
190
191     impl ToString for TokenStream {
192         fn to_string(&self) -> String {
193             let tt = self.subtree.clone().into();
194             to_text(&tt)
195         }
196     }
197
198     fn to_text(tkn: &tt::TokenTree) -> String {
199         match tkn {
200             tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.text.clone().into(),
201             tt::TokenTree::Leaf(tt::Leaf::Literal(literal)) => literal.text.clone().into(),
202             tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => format!("{}", punct.char),
203             tt::TokenTree::Subtree(subtree) => {
204                 let content = subtree
205                     .token_trees
206                     .iter()
207                     .map(|tkn| {
208                         let s = to_text(tkn);
209                         if let tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) = tkn {
210                             if punct.spacing == tt::Spacing::Alone {
211                                 return s + " ";
212                             }
213                         }
214                         s
215                     })
216                     .collect::<Vec<_>>()
217                     .concat();
218                 let (open, close) = match subtree.delimiter.map(|it| it.kind) {
219                     None => ("", ""),
220                     Some(tt::DelimiterKind::Brace) => ("{", "}"),
221                     Some(tt::DelimiterKind::Parenthesis) => ("(", ")"),
222                     Some(tt::DelimiterKind::Bracket) => ("[", "]"),
223                 };
224                 format!("{}{}{}", open, content, close)
225             }
226         }
227     }
228 }
229
230 impl TokenStreamBuilder {
231     fn new() -> TokenStreamBuilder {
232         TokenStreamBuilder { acc: TokenStream::new() }
233     }
234
235     fn push(&mut self, stream: TokenStream) {
236         self.acc.extend(stream.into_iter())
237     }
238
239     fn build(self) -> TokenStream {
240         self.acc
241     }
242 }
243
244 pub struct FreeFunctions;
245
246 #[derive(Clone)]
247 pub struct TokenStreamIter {
248     trees: IntoIter<TokenTree>,
249 }
250
251 #[derive(Default)]
252 pub struct Rustc {
253     ident_interner: IdentInterner,
254     // FIXME: store span information here.
255 }
256
257 impl server::Types for Rustc {
258     type FreeFunctions = FreeFunctions;
259     type TokenStream = TokenStream;
260     type TokenStreamBuilder = TokenStreamBuilder;
261     type TokenStreamIter = TokenStreamIter;
262     type Group = Group;
263     type Punct = Punct;
264     type Ident = IdentId;
265     type Literal = Literal;
266     type SourceFile = SourceFile;
267     type Diagnostic = Diagnostic;
268     type Span = Span;
269     type MultiSpan = Vec<Span>;
270 }
271
272 impl server::FreeFunctions for Rustc {
273     fn track_env_var(&mut self, _var: &str, _value: Option<&str>) {
274         // FIXME: track env var accesses
275         // https://github.com/rust-lang/rust/pull/71858
276     }
277 }
278
279 impl server::TokenStream for Rustc {
280     fn new(&mut self) -> Self::TokenStream {
281         Self::TokenStream::new()
282     }
283
284     fn is_empty(&mut self, stream: &Self::TokenStream) -> bool {
285         stream.is_empty()
286     }
287     fn from_str(&mut self, src: &str) -> Self::TokenStream {
288         Self::TokenStream::from_str(src).expect("cannot parse string")
289     }
290     fn to_string(&mut self, stream: &Self::TokenStream) -> String {
291         stream.to_string()
292     }
293     fn from_token_tree(
294         &mut self,
295         tree: bridge::TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>,
296     ) -> Self::TokenStream {
297         match tree {
298             bridge::TokenTree::Group(group) => {
299                 let tree = TokenTree::from(group);
300                 Self::TokenStream::from_iter(vec![tree])
301             }
302
303             bridge::TokenTree::Ident(IdentId(index)) => {
304                 let IdentData(ident) = self.ident_interner.get(index).clone();
305                 let ident: tt::Ident = ident;
306                 let leaf = tt::Leaf::from(ident);
307                 let tree = TokenTree::from(leaf);
308                 Self::TokenStream::from_iter(vec![tree])
309             }
310
311             bridge::TokenTree::Literal(literal) => {
312                 let leaf = tt::Leaf::from(literal);
313                 let tree = TokenTree::from(leaf);
314                 Self::TokenStream::from_iter(vec![tree])
315             }
316
317             bridge::TokenTree::Punct(p) => {
318                 let leaf = tt::Leaf::from(p);
319                 let tree = TokenTree::from(leaf);
320                 Self::TokenStream::from_iter(vec![tree])
321             }
322         }
323     }
324
325     fn into_iter(&mut self, stream: Self::TokenStream) -> Self::TokenStreamIter {
326         let trees: Vec<TokenTree> = stream.into_iter().collect();
327         TokenStreamIter { trees: trees.into_iter() }
328     }
329 }
330
331 impl server::TokenStreamBuilder for Rustc {
332     fn new(&mut self) -> Self::TokenStreamBuilder {
333         Self::TokenStreamBuilder::new()
334     }
335     fn push(&mut self, builder: &mut Self::TokenStreamBuilder, stream: Self::TokenStream) {
336         builder.push(stream)
337     }
338     fn build(&mut self, builder: Self::TokenStreamBuilder) -> Self::TokenStream {
339         builder.build()
340     }
341 }
342
343 impl server::TokenStreamIter for Rustc {
344     fn next(
345         &mut self,
346         iter: &mut Self::TokenStreamIter,
347     ) -> Option<bridge::TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>> {
348         iter.trees.next().map(|tree| match tree {
349             TokenTree::Subtree(group) => bridge::TokenTree::Group(group),
350             TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
351                 bridge::TokenTree::Ident(IdentId(self.ident_interner.intern(&IdentData(ident))))
352             }
353             TokenTree::Leaf(tt::Leaf::Literal(literal)) => bridge::TokenTree::Literal(literal),
354             TokenTree::Leaf(tt::Leaf::Punct(punct)) => bridge::TokenTree::Punct(punct),
355         })
356     }
357 }
358
359 fn delim_to_internal(d: bridge::Delimiter) -> Option<tt::Delimiter> {
360     let kind = match d {
361         bridge::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis,
362         bridge::Delimiter::Brace => tt::DelimiterKind::Brace,
363         bridge::Delimiter::Bracket => tt::DelimiterKind::Bracket,
364         bridge::Delimiter::None => return None,
365     };
366     Some(tt::Delimiter { id: tt::TokenId::unspecified(), kind })
367 }
368
369 fn delim_to_external(d: Option<tt::Delimiter>) -> bridge::Delimiter {
370     match d.map(|it| it.kind) {
371         Some(tt::DelimiterKind::Parenthesis) => bridge::Delimiter::Parenthesis,
372         Some(tt::DelimiterKind::Brace) => bridge::Delimiter::Brace,
373         Some(tt::DelimiterKind::Bracket) => bridge::Delimiter::Bracket,
374         None => bridge::Delimiter::None,
375     }
376 }
377
378 fn spacing_to_internal(spacing: bridge::Spacing) -> Spacing {
379     match spacing {
380         bridge::Spacing::Alone => Spacing::Alone,
381         bridge::Spacing::Joint => Spacing::Joint,
382     }
383 }
384
385 fn spacing_to_external(spacing: Spacing) -> bridge::Spacing {
386     match spacing {
387         Spacing::Alone => bridge::Spacing::Alone,
388         Spacing::Joint => bridge::Spacing::Joint,
389     }
390 }
391
392 impl server::Group for Rustc {
393     fn new(&mut self, delimiter: bridge::Delimiter, stream: Self::TokenStream) -> Self::Group {
394         Self::Group {
395             delimiter: delim_to_internal(delimiter),
396             token_trees: stream.subtree.token_trees,
397         }
398     }
399     fn delimiter(&mut self, group: &Self::Group) -> bridge::Delimiter {
400         delim_to_external(group.delimiter)
401     }
402
403     // NOTE: Return value of do not include delimiter
404     fn stream(&mut self, group: &Self::Group) -> Self::TokenStream {
405         TokenStream {
406             subtree: tt::Subtree { delimiter: None, token_trees: group.token_trees.clone() },
407         }
408     }
409
410     fn span(&mut self, group: &Self::Group) -> Self::Span {
411         group.delimiter.map(|it| it.id).unwrap_or_else(|| tt::TokenId::unspecified())
412     }
413
414     fn set_span(&mut self, _group: &mut Self::Group, _span: Self::Span) {
415         // FIXME handle span
416     }
417
418     fn span_open(&mut self, _group: &Self::Group) -> Self::Span {
419         // FIXME handle span
420         // MySpan(self.span_interner.intern(&MySpanData(group.span_open())))
421         tt::TokenId::unspecified()
422     }
423
424     fn span_close(&mut self, _group: &Self::Group) -> Self::Span {
425         // FIXME handle span
426         tt::TokenId::unspecified()
427     }
428 }
429
430 impl server::Punct for Rustc {
431     fn new(&mut self, ch: char, spacing: bridge::Spacing) -> Self::Punct {
432         tt::Punct {
433             char: ch,
434             spacing: spacing_to_internal(spacing),
435             id: tt::TokenId::unspecified(),
436         }
437     }
438     fn as_char(&mut self, punct: Self::Punct) -> char {
439         punct.char
440     }
441     fn spacing(&mut self, punct: Self::Punct) -> bridge::Spacing {
442         spacing_to_external(punct.spacing)
443     }
444     fn span(&mut self, _punct: Self::Punct) -> Self::Span {
445         // FIXME handle span
446         tt::TokenId::unspecified()
447     }
448     fn with_span(&mut self, punct: Self::Punct, _span: Self::Span) -> Self::Punct {
449         // FIXME handle span
450         punct
451     }
452 }
453
454 impl server::Ident for Rustc {
455     fn new(&mut self, string: &str, _span: Self::Span, _is_raw: bool) -> Self::Ident {
456         IdentId(
457             self.ident_interner.intern(&IdentData(tt::Ident {
458                 text: string.into(),
459                 id: tt::TokenId::unspecified(),
460             })),
461         )
462     }
463
464     fn span(&mut self, _ident: Self::Ident) -> Self::Span {
465         // FIXME handle span
466         tt::TokenId::unspecified()
467     }
468     fn with_span(&mut self, ident: Self::Ident, _span: Self::Span) -> Self::Ident {
469         // FIXME handle span
470         ident
471     }
472 }
473
474 impl server::Literal for Rustc {
475     fn debug_kind(&mut self, _literal: &Self::Literal) -> String {
476         // r-a: debug_kind and suffix are unsupported; corresponding client code has been changed to not call these.
477         // They must still be present to be ABI-compatible and work with upstream proc_macro.
478         "".to_owned()
479     }
480     fn symbol(&mut self, literal: &Self::Literal) -> String {
481         literal.text.to_string()
482     }
483     fn suffix(&mut self, _literal: &Self::Literal) -> Option<String> {
484         None
485     }
486
487     fn integer(&mut self, n: &str) -> Self::Literal {
488         let n: i128 = n.parse().unwrap();
489         Literal { text: n.to_string().into(), id: tt::TokenId::unspecified() }
490     }
491
492     fn typed_integer(&mut self, n: &str, kind: &str) -> Self::Literal {
493         macro_rules! def_suffixed_integer {
494             ($kind:ident, $($ty:ty),*) => {
495                 match $kind {
496                     $(
497                         stringify!($ty) => {
498                             let n: $ty = n.parse().unwrap();
499                             format!(concat!("{}", stringify!($ty)), n)
500                         }
501                     )*
502                     _ => unimplemented!("unknown args for typed_integer: n {}, kind {}", n, $kind),
503                 }
504             }
505         }
506
507         let text =
508             def_suffixed_integer! {kind, u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128};
509
510         Literal { text: text.into(), id: tt::TokenId::unspecified() }
511     }
512
513     fn float(&mut self, n: &str) -> Self::Literal {
514         let n: f64 = n.parse().unwrap();
515         let mut text = f64::to_string(&n);
516         if !text.contains('.') {
517             text += ".0"
518         }
519         Literal { text: text.into(), id: tt::TokenId::unspecified() }
520     }
521
522     fn f32(&mut self, n: &str) -> Self::Literal {
523         let n: f32 = n.parse().unwrap();
524         let text = format!("{}f32", n);
525         Literal { text: text.into(), id: tt::TokenId::unspecified() }
526     }
527
528     fn f64(&mut self, n: &str) -> Self::Literal {
529         let n: f64 = n.parse().unwrap();
530         let text = format!("{}f64", n);
531         Literal { text: text.into(), id: tt::TokenId::unspecified() }
532     }
533
534     fn string(&mut self, string: &str) -> Self::Literal {
535         let mut escaped = String::new();
536         for ch in string.chars() {
537             escaped.extend(ch.escape_debug());
538         }
539         Literal { text: format!("\"{}\"", escaped).into(), id: tt::TokenId::unspecified() }
540     }
541
542     fn character(&mut self, ch: char) -> Self::Literal {
543         Literal { text: format!("'{}'", ch).into(), id: tt::TokenId::unspecified() }
544     }
545
546     fn byte_string(&mut self, bytes: &[u8]) -> Self::Literal {
547         let string = bytes
548             .iter()
549             .cloned()
550             .flat_map(ascii::escape_default)
551             .map(Into::<char>::into)
552             .collect::<String>();
553
554         Literal { text: format!("b\"{}\"", string).into(), id: tt::TokenId::unspecified() }
555     }
556
557     fn span(&mut self, literal: &Self::Literal) -> Self::Span {
558         literal.id
559     }
560
561     fn set_span(&mut self, _literal: &mut Self::Literal, _span: Self::Span) {
562         // FIXME handle span
563     }
564
565     fn subspan(
566         &mut self,
567         _literal: &Self::Literal,
568         _start: Bound<usize>,
569         _end: Bound<usize>,
570     ) -> Option<Self::Span> {
571         // FIXME handle span
572         None
573     }
574 }
575
576 impl server::SourceFile for Rustc {
577     fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
578         file1.eq(file2)
579     }
580     fn path(&mut self, file: &Self::SourceFile) -> String {
581         String::from(
582             file.path().to_str().expect("non-UTF8 file path in `proc_macro::SourceFile::path`"),
583         )
584     }
585     fn is_real(&mut self, file: &Self::SourceFile) -> bool {
586         file.is_real()
587     }
588 }
589
590 impl server::Diagnostic for Rustc {
591     fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic {
592         let mut diag = Diagnostic::new(level, msg);
593         diag.spans = spans;
594         diag
595     }
596
597     fn sub(
598         &mut self,
599         _diag: &mut Self::Diagnostic,
600         _level: Level,
601         _msg: &str,
602         _spans: Self::MultiSpan,
603     ) {
604         // FIXME handle diagnostic
605         //
606     }
607
608     fn emit(&mut self, _diag: Self::Diagnostic) {
609         // FIXME handle diagnostic
610         // diag.emit()
611     }
612 }
613
614 impl server::Span for Rustc {
615     fn debug(&mut self, span: Self::Span) -> String {
616         format!("{:?}", span.0)
617     }
618     fn def_site(&mut self) -> Self::Span {
619         // MySpan(self.span_interner.intern(&MySpanData(Span::def_site())))
620         // FIXME handle span
621         tt::TokenId::unspecified()
622     }
623     fn call_site(&mut self) -> Self::Span {
624         // MySpan(self.span_interner.intern(&MySpanData(Span::call_site())))
625         // FIXME handle span
626         tt::TokenId::unspecified()
627     }
628     fn source_file(&mut self, _span: Self::Span) -> Self::SourceFile {
629         // let MySpanData(span) = self.span_interner.get(span.0);
630         unimplemented!()
631     }
632
633     /// Recent feature, not yet in the proc_macro
634     ///
635     /// See PR:
636     /// https://github.com/rust-lang/rust/pull/55780
637     fn source_text(&mut self, _span: Self::Span) -> Option<String> {
638         None
639     }
640
641     fn parent(&mut self, _span: Self::Span) -> Option<Self::Span> {
642         // FIXME handle span
643         None
644     }
645     fn source(&mut self, span: Self::Span) -> Self::Span {
646         // FIXME handle span
647         span
648     }
649     fn start(&mut self, _span: Self::Span) -> LineColumn {
650         // FIXME handle span
651         LineColumn { line: 0, column: 0 }
652     }
653     fn end(&mut self, _span: Self::Span) -> LineColumn {
654         // FIXME handle span
655         LineColumn { line: 0, column: 0 }
656     }
657     fn join(&mut self, _first: Self::Span, _second: Self::Span) -> Option<Self::Span> {
658         None
659     }
660     fn resolved_at(&mut self, _span: Self::Span, _at: Self::Span) -> Self::Span {
661         // FIXME handle span
662         tt::TokenId::unspecified()
663     }
664
665     fn mixed_site(&mut self) -> Self::Span {
666         // FIXME handle span
667         tt::TokenId::unspecified()
668     }
669 }
670
671 impl server::MultiSpan for Rustc {
672     fn new(&mut self) -> Self::MultiSpan {
673         // FIXME handle span
674         vec![]
675     }
676
677     fn push(&mut self, other: &mut Self::MultiSpan, span: Self::Span) {
678         //TODP
679         other.push(span)
680     }
681 }
682
683 #[cfg(test)]
684 mod tests {
685     use super::*;
686     use crate::proc_macro::bridge::server::Literal;
687
688     #[test]
689     fn test_rustc_server_literals() {
690         let mut srv = Rustc { ident_interner: IdentInterner::default() };
691         assert_eq!(srv.integer("1234").text, "1234");
692
693         assert_eq!(srv.typed_integer("12", "u8").text, "12u8");
694         assert_eq!(srv.typed_integer("255", "u16").text, "255u16");
695         assert_eq!(srv.typed_integer("1234", "u32").text, "1234u32");
696         assert_eq!(srv.typed_integer("15846685", "u64").text, "15846685u64");
697         assert_eq!(srv.typed_integer("15846685258", "u128").text, "15846685258u128");
698         assert_eq!(srv.typed_integer("156788984", "usize").text, "156788984usize");
699         assert_eq!(srv.typed_integer("127", "i8").text, "127i8");
700         assert_eq!(srv.typed_integer("255", "i16").text, "255i16");
701         assert_eq!(srv.typed_integer("1234", "i32").text, "1234i32");
702         assert_eq!(srv.typed_integer("15846685", "i64").text, "15846685i64");
703         assert_eq!(srv.typed_integer("15846685258", "i128").text, "15846685258i128");
704         assert_eq!(srv.float("0").text, "0.0");
705         assert_eq!(srv.float("15684.5867").text, "15684.5867");
706         assert_eq!(srv.f32("15684.58").text, "15684.58f32");
707         assert_eq!(srv.f64("15684.58").text, "15684.58f64");
708
709         assert_eq!(srv.string("hello_world").text, "\"hello_world\"");
710         assert_eq!(srv.character('c').text, "'c'");
711         assert_eq!(srv.byte_string(b"1234586\x88").text, "b\"1234586\\x88\"");
712     }
713 }