minisql/proto/src/message/primitive/pgstring.rs
2024-01-28 22:40:41 +01:00

74 lines
1.8 KiB
Rust

use bincode::de::Decoder;
use bincode::enc::write::Writer;
use bincode::enc::Encoder;
use bincode::error::{DecodeError, EncodeError};
use bincode::{BorrowDecode, Decode, Encode};
/// PostgreSQL format of string encoded as a null-terminated string.
#[derive(Debug, Clone, BorrowDecode)]
pub struct PgString(String);
impl PgString {
pub fn as_str(&self) -> &str {
&self.0
}
}
impl From<&str> for PgString {
fn from(string: &str) -> Self {
PgString(string.to_string())
}
}
impl From<PgString> for String {
fn from(pg_string: PgString) -> Self {
pg_string.0
}
}
impl From<String> for PgString {
fn from(string: String) -> Self {
PgString(string)
}
}
impl Encode for PgString {
fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
encoder.writer().write(self.0.as_bytes())?;
encoder.writer().write(b"\0")
}
}
impl Decode for PgString {
fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
let mut bytes = Vec::new();
loop {
let byte = u8::decode(decoder)?;
if byte == 0 {
break;
}
bytes.push(byte);
}
let string = String::from_utf8(bytes).map_err(|e| DecodeError::Utf8 {
inner: e.utf8_error(),
})?;
Ok(PgString(string))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::message::primitive::data::MessageData;
#[test]
fn test_encode_decode_utf8() {
let pg_string = PgString::from("áhój jěžkó");
let encoded = pg_string.serialize().unwrap();
let decoded: PgString = PgString::deserialize(&encoded).unwrap();
let actual = decoded.as_str();
assert_eq!("áhój jěžkó", actual);
}
}