curl/easy/
list.rs

1use std::ffi::{CStr, CString};
2use std::fmt;
3use std::ptr;
4
5use crate::Error;
6
7/// A linked list of a strings
8pub struct List {
9    raw: *mut curl_sys::curl_slist,
10}
11
12/// An iterator over `List`
13#[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    /// Creates a new empty list of strings.
31    pub fn new() -> List {
32        List {
33            raw: ptr::null_mut(),
34        }
35    }
36
37    /// Appends some data into this list.
38    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    /// Returns an iterator over the nodes in this list.
49    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}