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}