瀏覽代碼

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 年之前
父節點
當前提交
bdd1228494
共有 2 個文件被更改,包括 24 次插入28 次删除
  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())),
         ]))
     );
 }