1use std::ffi::{CStr, CString};
2use std::fmt;
3use std::ptr;
4
5use crate::Error;
6
7pub struct List {
9 raw: *mut curl_sys::curl_slist,
10}
11
12#[derive(Clone)]
14pub struct Iter<'a> {
15 _me: &'a List,
16 cur: *mut curl_sys::curl_slist,
17}
18
19pub fn raw(list: &List) -> *mut curl_sys::curl_slist {
20 list.raw
21}
22
23pub unsafe fn from_raw(raw: *mut curl_sys::curl_slist) -> List {
24 List { raw }
25}
26
27unsafe impl Send for List {}
28
29impl List {
30 pub fn new() -> List {
32 List {
33 raw: ptr::null_mut(),
34 }
35 }
36
37 pub fn append(&mut self, data: &str) -> Result<(), Error> {
39 let data = CString::new(data)?;
40 unsafe {
41 let raw = curl_sys::curl_slist_append(self.raw, data.as_ptr());
42 assert!(!raw.is_null());
43 self.raw = raw;
44 Ok(())
45 }
46 }
47
48 pub fn iter(&self) -> Iter<'_> {
50 Iter {
51 _me: self,
52 cur: self.raw,
53 }
54 }
55}
56
57impl fmt::Debug for List {
58 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59 f.debug_list()
60 .entries(self.iter().map(String::from_utf8_lossy))
61 .finish()
62 }
63}
64
65impl<'a> IntoIterator for &'a List {
66 type IntoIter = Iter<'a>;
67 type Item = &'a [u8];
68
69 fn into_iter(self) -> Iter<'a> {
70 self.iter()
71 }
72}
73
74impl Drop for List {
75 fn drop(&mut self) {
76 unsafe { curl_sys::curl_slist_free_all(self.raw) }
77 }
78}
79
80impl<'a> Iterator for Iter<'a> {
81 type Item = &'a [u8];
82
83 fn next(&mut self) -> Option<&'a [u8]> {
84 if self.cur.is_null() {
85 return None;
86 }
87
88 unsafe {
89 let ret = Some(CStr::from_ptr((*self.cur).data).to_bytes());
90 self.cur = (*self.cur).next;
91 ret
92 }
93 }
94}
95
96impl<'a> fmt::Debug for Iter<'a> {
97 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98 f.debug_list()
99 .entries(self.clone().map(String::from_utf8_lossy))
100 .finish()
101 }
102}