foreign/impl/
cow.rs

1use std::borrow::Cow;
2
3use crate::foreign::*;
4
5impl<'a, B> FreeForeign for Cow<'a, B>
6where
7    B: 'a + ToOwned + ?Sized + FreeForeign,
8{
9    type Foreign = B::Foreign;
10
11    unsafe fn free_foreign(ptr: *mut B::Foreign) {
12        B::free_foreign(ptr);
13    }
14}
15
16impl<'a, B> CloneToForeign for Cow<'a, B>
17where
18    B: 'a + ToOwned + ?Sized + CloneToForeign,
19{
20    fn clone_to_foreign(&self) -> OwnedPointer<Self> {
21        (**self).clone_to_foreign().into()
22    }
23}
24
25impl<'a, B> BorrowForeign<'a> for Cow<'a, B>
26where
27    B: 'a + ToOwned + ?Sized + BorrowForeign<'a>,
28{
29    type Storage = B::Storage;
30
31    fn borrow_foreign(&'a self) -> BorrowedPointer<Self, B::Storage> {
32        (**self).borrow_foreign().into()
33    }
34}
35
36impl<'a, B> FromForeign for Cow<'a, B>
37where
38    B: 'a + ToOwned + ?Sized + FreeForeign,
39    <B as ToOwned>::Owned: FromForeign + FreeForeign<Foreign = B::Foreign>,
40{
41    unsafe fn cloned_from_foreign(ptr: *const B::Foreign) -> Self {
42        let cloned: <B as ToOwned>::Owned = FromForeign::cloned_from_foreign(ptr);
43        Cow::Owned(cloned)
44    }
45}
46
47impl<'a, B> IntoForeign for Cow<'a, B>
48where
49    B: 'a + ToOwned + ?Sized + FreeForeign,
50    <B as ToOwned>::Owned: IntoForeign + FreeForeign<Foreign = B::Foreign>,
51{
52    type Storage = <B::Owned as IntoForeign>::Storage;
53
54    fn into_foreign(self) -> BorrowedMutPointer<Self, Self::Storage> {
55        self.into_owned().into_foreign().into()
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use std::borrow::Cow;
62    use std::ffi::{c_void, CStr};
63
64    use crate::c_str::c_str;
65    use crate::foreign::*;
66
67    #[test]
68    fn test_cloned_from_foreign_string_cow() {
69        let s = "Hello, world!".to_string();
70        let cstr = c_str!("Hello, world!");
71        let cloned = unsafe { Cow::cloned_from_foreign(cstr.as_ptr()) };
72        assert_eq!(s, cloned);
73    }
74
75    #[test]
76    fn test_clone_to_foreign_string_cow() {
77        let p = c_str!("Hello, world!").as_ptr();
78        for s in [
79            Into::<Cow<str>>::into("Hello, world!"),
80            Into::<Cow<str>>::into("Hello, world!".to_string()),
81        ] {
82            let cloned = s.clone_to_foreign();
83            unsafe {
84                let len = libc::strlen(cloned.as_ptr());
85                assert_eq!(len, s.len());
86                assert_eq!(
87                    libc::memcmp(
88                        cloned.as_ptr().cast::<c_void>(),
89                        p.cast::<c_void>(),
90                        len + 1
91                    ),
92                    0
93                );
94            }
95        }
96    }
97
98    #[test]
99    fn test_borrow_foreign_string_cow() {
100        let p = c_str!("Hello, world!").as_ptr();
101        for s in [
102            Into::<Cow<CStr>>::into(c_str!("Hello, world!")),
103            Into::<Cow<CStr>>::into(c_str!("Hello, world!").to_owned()),
104        ] {
105            let borrowed = s.borrow_foreign();
106            unsafe {
107                let len = libc::strlen(borrowed.as_ptr());
108                assert_eq!(len, libc::strlen(p));
109                assert_eq!(
110                    libc::memcmp(
111                        borrowed.as_ptr().cast::<c_void>(),
112                        p.cast::<c_void>(),
113                        len + 1
114                    ),
115                    0
116                );
117            }
118        }
119    }
120
121    #[test]
122    fn test_into_foreign_string_cow() {
123        let p = c_str!("Hello, world!").as_ptr();
124        for s in [
125            Into::<Cow<str>>::into("Hello, world!"),
126            Into::<Cow<str>>::into("Hello, world!".to_string()),
127        ] {
128            let consumed = s.into_foreign();
129            unsafe {
130                let len = libc::strlen(consumed.as_ptr());
131                assert_eq!(len, libc::strlen(p));
132                assert_eq!(
133                    libc::memcmp(
134                        consumed.as_ptr().cast::<c_void>(),
135                        p.cast::<c_void>(),
136                        len + 1
137                    ),
138                    0
139                );
140            }
141        }
142    }
143}