surrealdb_core/syn/lexer/compound/
uuid.rs1use crate::syn::{
2 error::{bail, SyntaxError},
3 lexer::Lexer,
4 token::{t, Token},
5};
6use uuid::Uuid;
7
8pub fn uuid(lexer: &mut Lexer, start: Token) -> Result<Uuid, SyntaxError> {
9 let double = match start.kind {
10 t!("u\"") => true,
11 t!("u'") => false,
12 x => panic!("Invalid start token of uuid compound: {x}"),
13 };
14
15 let mut uuid_buffer = [0u8; 16];
16 eat_uuid_hex(lexer, &mut uuid_buffer[0..4])?;
19
20 lexer.expect('-')?;
21
22 eat_uuid_hex(lexer, &mut uuid_buffer[4..6])?;
23
24 lexer.expect('-')?;
25
26 eat_uuid_hex(lexer, &mut uuid_buffer[6..8])?;
27
28 lexer.expect('-')?;
29
30 eat_uuid_hex(lexer, &mut uuid_buffer[8..10])?;
31
32 lexer.expect('-')?;
33
34 eat_uuid_hex(lexer, &mut uuid_buffer[10..16])?;
35
36 if double {
37 lexer.expect('"')?;
38 } else {
39 lexer.expect('\'')?;
40 }
41
42 Ok(Uuid::from_bytes(uuid_buffer))
43}
44
45fn eat_uuid_hex(lexer: &mut Lexer, buffer: &mut [u8]) -> Result<(), SyntaxError> {
46 for x in buffer {
49 let a = eat_hex_character(lexer)?;
50 let b = eat_hex_character(lexer)?;
51 *x = (a << 4) | b;
52 }
53
54 Ok(())
55}
56
57fn eat_hex_character(lexer: &mut Lexer) -> Result<u8, SyntaxError> {
58 fn ascii_to_hex(b: u8) -> Option<u8> {
59 if b.is_ascii_digit() {
60 return Some(b - b'0');
61 }
62
63 if (b'a'..=b'f').contains(&b) {
64 return Some(b - (b'a' - 10));
65 }
66
67 if (b'A'..=b'F').contains(&b) {
68 return Some(b - (b'A' - 10));
69 }
70
71 None
72 }
73
74 let Some(peek) = lexer.reader.peek() else {
75 bail!("Unexpected end of file, expected UUID token to finish",@lexer.current_span());
76 };
77 let Some(res) = ascii_to_hex(peek) else {
78 lexer.advance_span();
79 let char = lexer.reader.next().unwrap();
80 let char = lexer.reader.convert_to_char(char)?;
81 bail!("Unexpected character `{char}` expected hexidecimal digit",@lexer.current_span());
82 };
83 lexer.reader.next();
84 Ok(res)
85}