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