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 fn push(&mut self, value: T) -> Result<(), Self::Error>;
11
12 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#[cfg_attr(any(feature = "fmt", test, debug_assertions), derive(Debug))]
32#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
33pub enum SqlExpr<'ex, T> {
34 Value(T),
36 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#[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}