surrealdb_core/syn/lexer/compound/
uuid.rs

1use 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	// number of bytes is 4-2-2-2-6
17
18	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	// the amounts of character required is twice the buffer len.
47	// since every character is half a byte.
48	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}