Use NonNull with ParameterStatus

This commit is contained in:
Ryan Leckey 2019-08-19 21:30:07 -07:00
parent 1822d25b76
commit 09c744d0b9

View File

@ -1,42 +1,52 @@
use super::Decode;
use bytes::Bytes;
use super::decode::{Decode, get_str};
use std::pin::Pin;
use std::ptr::NonNull;
use std::{io, str};
// FIXME: Use &str functions for a custom Debug
#[derive(Debug)]
pub struct ParameterStatus {
name: Vec<u8>,
value: Vec<u8>,
#[used]
storage: Pin<Vec<u8>>,
name: NonNull<str>,
value: NonNull<str>,
}
// SAFE: Raw pointers point to pinned memory inside the struct
unsafe impl Send for ParameterStatus {}
unsafe impl Sync for ParameterStatus {}
impl ParameterStatus {
#[inline]
pub fn name(&self) -> &str {
unsafe { str::from_utf8_unchecked(&self.name) }
// SAFE: Memory is pinned
unsafe { self.name.as_ref() }
}
#[inline]
pub fn value(&self) -> &str {
unsafe { str::from_utf8_unchecked(&self.value) }
// SAFE: Memory is pinned
unsafe { self.value.as_ref() }
}
}
impl Decode for ParameterStatus {
fn decode(src: &[u8]) -> io::Result<Self> {
let name_end = memchr::memchr(0, &src).unwrap();
let value_end = memchr::memchr(0, &src[(name_end + 1)..]).unwrap();
let storage = Pin::new(Vec::from(src));
let name = src[..name_end].into();
let value = src[(name_end + 1)..(name_end + 1 + value_end)].into();
let name = get_str(&storage).unwrap();
let value = get_str(&storage[name.len() + 1..]).unwrap();
Ok(Self { name, value })
let name = NonNull::from(name);
let value = NonNull::from(value);
Ok(Self { storage, name, value })
}
}
#[cfg(test)]
mod tests {
use super::{Decode, ParameterStatus};
use bytes::Bytes;
use std::io;
const PARAM_STATUS: &[u8] = b"session_authorization\0postgres\0";