1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
use std::convert::TryFrom;

use wasm_bindgen::JsCast;

use crate::console::{Write, Writer};
use crate::html::HtmlLabelElement;

pub struct Labels {
    inner: web_sys::NodeList,
}

impl Labels {
    pub(crate) fn new(inner: web_sys::NodeList) -> Self {
        Labels { inner }
    }

    pub fn get(&self, index: usize) -> Option<HtmlLabelElement> {
        u32::try_from(index)
            .ok()
            .and_then(|index| self.inner.get(index))
            .map(|n| {
                let label: web_sys::HtmlLabelElement = n.unchecked_into();

                HtmlLabelElement::from(label)
            })
    }

    pub fn len(&self) -> usize {
        self.inner.length() as usize
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn is_not_empty(&self) -> bool {
        !self.is_empty()
    }

    pub fn first(&self) -> Option<HtmlLabelElement> {
        self.get(0)
    }

    pub fn last(&self) -> Option<HtmlLabelElement> {
        let len = self.len();

        if len > 0 {
            self.get(len - 1)
        } else {
            None
        }
    }

    pub fn iter(&self) -> LabelsIter {
        LabelsIter {
            labels: self,
            current: 0,
        }
    }
}

impl Write for Labels {
    fn write(&self, writer: &mut Writer) {
        writer.write_1(self.inner.as_ref());
    }
}

impl IntoIterator for Labels {
    type Item = HtmlLabelElement;
    type IntoIter = LabelsIntoIter;

    fn into_iter(self) -> Self::IntoIter {
        LabelsIntoIter {
            labels: self,
            current: 0,
        }
    }
}

pub struct LabelsIter<'a> {
    labels: &'a Labels,
    current: usize,
}

impl<'a> Iterator for LabelsIter<'a> {
    type Item = HtmlLabelElement;

    fn next(&mut self) -> Option<Self::Item> {
        let current = self.current;

        self.current += 1;

        self.labels.get(current)
    }
}

pub struct LabelsIntoIter {
    labels: Labels,
    current: usize,
}

impl Iterator for LabelsIntoIter {
    type Item = HtmlLabelElement;

    fn next(&mut self) -> Option<Self::Item> {
        let current = self.current;

        self.current += 1;

        self.labels.get(current)
    }
}