Browse Source

Make `Label` own its contents

We expect to pass these around after the initial buffer they were parsed
out of (most likely JSON from GitHub) has been deallocated. That
requires us to own the data.

If this becomes a performance concern we can investigate interning the
labels - we are essentially guaranteed to have a relatively small set of
labels around in the long term.
Mark Rousskov 6 năm trước cách đây
mục cha
commit
bdd1228494
2 tập tin đã thay đổi với 24 bổ sung28 xóa
  1. 3 3
      parser/src/command.rs
  2. 21 25
      parser/src/command/label.rs

+ 3 - 3
parser/src/command.rs

@@ -9,8 +9,8 @@ pub fn find_commmand_start(input: &str, bot: &str) -> Option<usize> {
 }
 
 #[derive(Debug)]
-pub enum Command<'a> {
-    Label(label::LabelCommand<'a>),
+pub enum Command {
+    Label(label::LabelCommand),
 }
 
 #[derive(Debug)]
@@ -31,7 +31,7 @@ impl<'a> Input<'a> {
         }
     }
 
-    pub fn parse_command(&mut self) -> Result<Option<Command<'a>>, Error<'a>> {
+    pub fn parse_command(&mut self) -> Result<Option<Command>, Error<'a>> {
         let start = match find_commmand_start(&self.all[self.parsed..], self.bot) {
             Some(pos) => pos,
             None => return Ok(None),

+ 21 - 25
parser/src/command/label.rs

@@ -30,16 +30,16 @@ use std::error::Error as _;
 use std::fmt;
 
 #[derive(Debug)]
-pub struct LabelCommand<'a>(Vec<LabelDelta<'a>>);
+pub struct LabelCommand(Vec<LabelDelta>);
 
 #[derive(Debug, PartialEq, Eq)]
-pub enum LabelDelta<'a> {
-    Add(Label<'a>),
-    Remove(Label<'a>),
+pub enum LabelDelta {
+    Add(Label),
+    Remove(Label),
 }
 
-#[derive(Debug, PartialEq, Eq, Copy, Clone)]
-pub struct Label<'a>(&'a str);
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub struct Label(String);
 
 #[derive(PartialEq, Eq, Debug)]
 pub enum ParseError {
@@ -62,29 +62,25 @@ impl fmt::Display for ParseError {
     }
 }
 
-impl<'a> Label<'a> {
-    fn parse(input: &'a str) -> Result<Label<'a>, ParseError> {
+impl Label {
+    fn parse(input: &str) -> Result<Label, ParseError> {
         if input.is_empty() {
             Err(ParseError::EmptyLabel)
         } else {
-            Ok(Label(input))
+            Ok(Label(input.into()))
         }
     }
-
-    pub fn as_str(&self) -> &'a str {
-        self.0
-    }
 }
 
-impl<'a> std::ops::Deref for Label<'a> {
-    type Target = str;
-    fn deref(&self) -> &str {
-        self.0
+impl std::ops::Deref for Label {
+    type Target = String;
+    fn deref(&self) -> &String {
+        &self.0
     }
 }
 
-impl<'a> LabelDelta<'a> {
-    fn parse(input: &mut Tokenizer<'a>) -> Result<LabelDelta<'a>, Error<'a>> {
+impl LabelDelta {
+    fn parse<'a>(input: &mut Tokenizer<'a>) -> Result<LabelDelta, Error<'a>> {
         let delta = match input.peek_token()? {
             Some(Token::Word(delta)) => {
                 input.next_token()?;
@@ -121,8 +117,8 @@ fn delta_empty() {
     assert_eq!(err.position(), 1);
 }
 
-impl<'a> LabelCommand<'a> {
-    pub fn parse(input: &mut Tokenizer<'a>) -> Result<Option<Self>, Error<'a>> {
+impl LabelCommand {
+    pub fn parse<'a>(input: &mut Tokenizer<'a>) -> Result<Option<Self>, Error<'a>> {
         let mut toks = input.clone();
         if let Some(Token::Word("modify")) = toks.next_token()? {
             // continue
@@ -167,7 +163,7 @@ impl<'a> LabelCommand<'a> {
 }
 
 #[cfg(test)]
-fn parse<'a>(input: &'a str) -> Result<Option<Vec<LabelDelta<'a>>>, Error<'a>> {
+fn parse<'a>(input: &'a str) -> Result<Option<Vec<LabelDelta>>, Error<'a>> {
     let mut toks = Tokenizer::new(input);
     Ok(LabelCommand::parse(&mut toks)?.map(|c| c.0))
 }
@@ -177,9 +173,9 @@ fn parse_simple() {
     assert_eq!(
         parse("modify labels: +T-compiler -T-lang bug."),
         Ok(Some(vec![
-            LabelDelta::Add(Label("T-compiler")),
-            LabelDelta::Remove(Label("T-lang")),
-            LabelDelta::Add(Label("bug")),
+            LabelDelta::Add(Label("T-compiler".into())),
+            LabelDelta::Remove(Label("T-lang".into())),
+            LabelDelta::Add(Label("bug".into())),
         ]))
     );
 }