1use crate::encode::{Encode, IsNull};
2use crate::types::Type;
3use crate::{MySql, MySqlTypeInfo};
4pub(crate) use sqlx_core::arguments::*;
5use sqlx_core::error::BoxDynError;
6use std::ops::Deref;
7
8#[derive(Debug, Default, Clone)]
10pub struct MySqlArguments {
11 pub(crate) values: Vec<u8>,
12 pub(crate) types: Vec<MySqlTypeInfo>,
13 pub(crate) null_bitmap: NullBitMap,
14}
15
16impl MySqlArguments {
17 pub(crate) fn add<'q, T>(&mut self, value: T) -> Result<(), BoxDynError>
18 where
19 T: Encode<'q, MySql> + Type<MySql>,
20 {
21 let ty = value.produces().unwrap_or_else(T::type_info);
22
23 let value_length_before_encoding = self.values.len();
24 let is_null = match value.encode(&mut self.values) {
25 Ok(is_null) => is_null,
26 Err(error) => {
27 self.values.truncate(value_length_before_encoding);
29 return Err(error);
30 }
31 };
32
33 self.types.push(ty);
34 self.null_bitmap.push(is_null);
35
36 Ok(())
37 }
38}
39
40impl<'q> Arguments<'q> for MySqlArguments {
41 type Database = MySql;
42
43 fn reserve(&mut self, len: usize, size: usize) {
44 self.types.reserve(len);
45 self.values.reserve(size);
46 }
47
48 fn add<T>(&mut self, value: T) -> Result<(), BoxDynError>
49 where
50 T: Encode<'q, Self::Database> + Type<Self::Database>,
51 {
52 self.add(value)
53 }
54
55 fn len(&self) -> usize {
56 self.types.len()
57 }
58}
59
60#[derive(Debug, Default, Clone)]
61pub(crate) struct NullBitMap {
62 bytes: Vec<u8>,
63 length: usize,
64}
65
66impl NullBitMap {
67 fn push(&mut self, is_null: IsNull) {
68 let byte_index = self.length / (u8::BITS as usize);
69 let bit_offset = self.length % (u8::BITS as usize);
70
71 if bit_offset == 0 {
72 self.bytes.push(0);
73 }
74
75 self.bytes[byte_index] |= u8::from(is_null.is_null()) << bit_offset;
76 self.length += 1;
77 }
78}
79
80impl Deref for NullBitMap {
81 type Target = [u8];
82
83 fn deref(&self) -> &Self::Target {
84 &self.bytes
85 }
86}
87
88#[cfg(test)]
89mod test {
90 use super::*;
91
92 #[test]
93 fn null_bit_map_should_push_is_null() {
94 let mut bit_map = NullBitMap::default();
95
96 bit_map.push(IsNull::Yes);
97 bit_map.push(IsNull::No);
98 bit_map.push(IsNull::Yes);
99 bit_map.push(IsNull::No);
100 bit_map.push(IsNull::Yes);
101 bit_map.push(IsNull::No);
102 bit_map.push(IsNull::Yes);
103 bit_map.push(IsNull::No);
104 bit_map.push(IsNull::Yes);
105
106 assert_eq!([0b01010101, 0b1].as_slice(), bit_map.deref());
107 }
108}