1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use std::error::Error;
use std::marker::PhantomData;

use super::null_ptr_error;
use super::{FromForeign, InputType, ReturnType, Slice, ToForeign};

pub struct StrMarshaler<'a>(&'a PhantomData<()>);

impl InputType for StrMarshaler<'_> {
    type Foreign = Slice<u8>;
}

impl ReturnType for StrMarshaler<'_> {
    type Foreign = Slice<u8>;

    #[inline(always)]
    fn foreign_default() -> Self::Foreign {
        Slice::default()
    }
}

impl<'a> ToForeign<&'a str, Slice<u8>> for StrMarshaler<'a> {
    type Error = Box<dyn Error>;

    #[inline(always)]
    fn to_foreign(input: &'a str) -> Result<Slice<u8>, Self::Error> {
        let bytes = input.to_owned().into_boxed_str().into_boxed_bytes();
        let len = bytes.len();

        Ok(Slice {
            data: Box::into_raw(bytes) as _,
            len,
        })
    }
}

impl<'a> FromForeign<Slice<u8>, &'a str> for StrMarshaler<'a> {
    type Error = Box<dyn Error>;

    #[inline(always)]
    unsafe fn from_foreign(slice: Slice<u8>) -> Result<&'a str, Self::Error> {
        if slice.data.is_null() {
            return Err(null_ptr_error());
        }

        let r = std::slice::from_raw_parts(slice.data as _, slice.len);
        std::str::from_utf8(r).map_err(|e| Box::new(e) as _)
    }
}

impl<'a> FromForeign<Slice<u8>, Option<&'a str>> for StrMarshaler<'a> {
    type Error = Box<dyn Error>;

    #[inline(always)]
    unsafe fn from_foreign(slice: Slice<u8>) -> Result<Option<&'a str>, Self::Error> {
        if slice.data.is_null() {
            return Ok(None);
        }

        let r = std::slice::from_raw_parts(slice.data as _, slice.len);
        std::str::from_utf8(r)
            .map(Some)
            .map_err(|e| Box::new(e) as _)
    }
}