sqlstr/
base.rs

1use alloc::string::String;
2use core::convert::Infallible;
3
4use crate::format_num::format_u32_base10;
5
6pub trait ArgumentBuffer<T> {
7    type Error;
8
9    /// Push a new argument into the buffer
10    fn push(&mut self, value: T) -> Result<(), Self::Error>;
11
12    /// Returns the number of arguments pushed into `Self`
13    fn count(&self) -> u32;
14}
15
16pub trait WriteSql<Arg> {
17    fn push_expr<T>(&mut self, operand: SqlExpr<'_, T>) -> Result<(), Arg::Error>
18    where
19        Arg: ArgumentBuffer<T>;
20
21    fn push_value<T>(&mut self, value: T) -> Result<(), Arg::Error>
22    where
23        Arg: ArgumentBuffer<T>;
24
25    fn push_cmd(&mut self, expr: &str);
26
27    fn as_command(&self) -> &str;
28}
29
30/// SQL Fragment
31#[cfg_attr(any(feature = "fmt", test, debug_assertions), derive(Debug))]
32#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
33pub enum SqlExpr<'ex, T> {
34    /// Value of a sql command argument.
35    Value(T),
36    /// Expression of a sql command.
37    Expr(&'ex str),
38}
39
40pub const fn sqlexpr<T>(expr: &str) -> SqlExpr<'_, T> {
41    SqlExpr::Expr(expr)
42}
43
44pub const fn sqlvalue<T>(expr: T) -> SqlExpr<'static, T> {
45    SqlExpr::Value(expr)
46}
47
48#[cfg_attr(any(feature = "fmt", test, debug_assertions), derive(Debug))]
49#[derive(Clone, Default, PartialEq, Eq)]
50pub struct SqlCommand<Arg> {
51    pub command: String,
52    pub arguments: Arg,
53}
54
55impl<Arg> SqlCommand<Arg> {
56    pub const fn new(command: String, arguments: Arg) -> Self {
57        Self { command, arguments }
58    }
59
60    pub fn push_expr<T>(&mut self, operand: SqlExpr<'_, T>) -> Result<(), Arg::Error>
61    where
62        Arg: ArgumentBuffer<T>,
63    {
64        match operand {
65            SqlExpr::Value(val) => self.push_value(val)?,
66            SqlExpr::Expr(expr) => self.command.push_str(expr),
67        }
68        Ok(())
69    }
70
71    pub fn push_value<T>(&mut self, value: T) -> Result<(), Arg::Error>
72    where
73        Arg: ArgumentBuffer<T>,
74    {
75        self.arguments.push(value)?;
76        let mut buf = [0; 10];
77        self.command.push('$');
78        self.command
79            .push_str(format_u32_base10(self.arguments.count(), &mut buf));
80        Ok(())
81    }
82
83    pub fn push_cmd(&mut self, expr: &str) {
84        self.command.push_str(expr);
85    }
86
87    pub fn as_command(&self) -> &str {
88        self.command.as_str()
89    }
90}
91
92impl<Arg> WriteSql<Arg> for SqlCommand<Arg> {
93    fn push_expr<T>(&mut self, operand: SqlExpr<'_, T>) -> Result<(), Arg::Error>
94    where
95        Arg: ArgumentBuffer<T>,
96    {
97        SqlCommand::push_expr(self, operand)
98    }
99
100    fn push_value<T>(&mut self, val: T) -> Result<(), <Arg>::Error>
101    where
102        Arg: ArgumentBuffer<T>,
103    {
104        SqlCommand::push_value(self, val)
105    }
106
107    fn push_cmd(&mut self, expr: &str) {
108        SqlCommand::push_cmd(self, expr)
109    }
110
111    fn as_command(&self) -> &str {
112        self.command.as_str()
113    }
114}
115
116/// Void argument buffer
117///
118/// This [ArgumentBuffer] does not hold any argument written.
119#[cfg_attr(any(feature = "fmt", test, debug_assertions), derive(Debug))]
120#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
121pub struct Void(u32);
122
123impl Void {
124    pub const fn new() -> Self {
125        Self(0)
126    }
127
128    pub const fn with_count(count: u32) -> Self {
129        Self(count)
130    }
131
132    pub const fn count(&self) -> u32 {
133        self.0
134    }
135}
136
137impl<T> ArgumentBuffer<T> for Void {
138    type Error = Infallible;
139
140    fn push(&mut self, _: T) -> Result<(), Self::Error> {
141        self.0 += 1;
142        Ok(())
143    }
144
145    fn count(&self) -> u32 {
146        self.0
147    }
148}