surrealdb_core/syn/lexer/compound/
uuid.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use crate::syn::{
	error::{bail, SyntaxError},
	lexer::Lexer,
	token::{t, Token},
};
use uuid::Uuid;

pub fn uuid(lexer: &mut Lexer, start: Token) -> Result<Uuid, SyntaxError> {
	let double = match start.kind {
		t!("u\"") => true,
		t!("u'") => false,
		x => panic!("Invalid start token of uuid compound: {x}"),
	};

	let mut uuid_buffer = [0u8; 16];
	// number of bytes is 4-2-2-2-6

	eat_uuid_hex(lexer, &mut uuid_buffer[0..4])?;

	lexer.expect('-')?;

	eat_uuid_hex(lexer, &mut uuid_buffer[4..6])?;

	lexer.expect('-')?;

	eat_uuid_hex(lexer, &mut uuid_buffer[6..8])?;

	lexer.expect('-')?;

	eat_uuid_hex(lexer, &mut uuid_buffer[8..10])?;

	lexer.expect('-')?;

	eat_uuid_hex(lexer, &mut uuid_buffer[10..16])?;

	if double {
		lexer.expect('"')?;
	} else {
		lexer.expect('\'')?;
	}

	Ok(Uuid::from_bytes(uuid_buffer))
}

fn eat_uuid_hex(lexer: &mut Lexer, buffer: &mut [u8]) -> Result<(), SyntaxError> {
	// the amounts of character required is twice the buffer len.
	// since every character is half a byte.
	for x in buffer {
		let a = eat_hex_character(lexer)?;
		let b = eat_hex_character(lexer)?;
		*x = (a << 4) | b;
	}

	Ok(())
}

fn eat_hex_character(lexer: &mut Lexer) -> Result<u8, SyntaxError> {
	fn ascii_to_hex(b: u8) -> Option<u8> {
		if b.is_ascii_digit() {
			return Some(b - b'0');
		}

		if (b'a'..=b'f').contains(&b) {
			return Some(b - (b'a' - 10));
		}

		if (b'A'..=b'F').contains(&b) {
			return Some(b - (b'A' - 10));
		}

		None
	}

	let Some(peek) = lexer.reader.peek() else {
		bail!("Unexpected end of file, expected UUID token to finish",@lexer.current_span());
	};
	let Some(res) = ascii_to_hex(peek) else {
		lexer.advance_span();
		let char = lexer.reader.next().unwrap();
		let char = lexer.reader.convert_to_char(char)?;
		bail!("Unexpected character `{char}` expected hexidecimal digit",@lexer.current_span());
	};
	lexer.reader.next();
	Ok(res)
}