Sanitize and build data structure from Consul configurationLoading site configuration from ini fileConfiguration concept and implementationNode.JS module to retrieve configuration from environment variablesLoading configuration properties from XMLReading and writing configuration fileA class to load, check and supply configuration data from a .py fileApp that sets configuration dataEditing a configuration file using C++ and Win32

What does "綺麗" mean in this sentence?

Pass a bash variable to python script

Novel set in the future, children cannot change the class they are born into, one class is made uneducated by associating books with pain

7 mentions of night in Gospel of John

Where does the tea come from?

Does the warlock's Gift of the Ever-Living Ones eldritch invocation work with potions or healing spells cast on you by others?

Extra battery in the gap of an HDD

Marxist and post modernism contradiction

d-Menthol vs dl-menthol: Does an enantiomer and its racemic mixture have different melting points?

Is there any restriction in entering the South American countries multiple times in one year?

Where is the 'zone of reversed commands...'?

Is a light year a different distance if measured from a moving object?

Do you say "good game" after a game in which your opponent played poorly?

Using Terminal` (ASCII plots) in Wolfram 12

What is the name for a fluid transition between two tones? When did it first appear?

Can digital computers understand infinity?

Dynamics m, r, s, and z. What do they mean?

Proofreading a novel: is it okay to use a question mark with an exclamation mark - "?!"

Can you take an Immortal Phoenix out of the game?

Some interesting and elementary topics with connections to the representation theory?

Do I need to explicitly handle negative numbers or zero when summing squared digits?

counter in hexadecimal base

A fast aquatic predator with multiple eyes and pupils. Would these eyes be possible?

Does a reincarnated Draconic Bloodline Sorcerer save his class abilities?



Sanitize and build data structure from Consul configuration


Loading site configuration from ini fileConfiguration concept and implementationNode.JS module to retrieve configuration from environment variablesLoading configuration properties from XMLReading and writing configuration fileA class to load, check and supply configuration data from a .py fileApp that sets configuration dataEditing a configuration file using C++ and Win32






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;









3














$begingroup$


I have a piece of working code that takes some strings from Consul configuration exports, sanitizes them a little and converts them into valid json and/or hocon structures.



While I am iterating over a vector of Nodes in the process function, I couldn't come up with a better solution than having to clone them. After inspecting some related APIs and looking for possible solutions, I understand (hopefully correctly) that it's a baked-in feature of Rust that you cannot move the ownership of the 'iteratee' to the result of the iteration.



Probably, I have to re-write everything in order to optimize the performance, but I need to research more to understand what would be the most idiomatic way to write this in Rust.



In the process I'm cloning the Vec's of Node's. I want to collect them as Node's, and not as &Node's, and this doesn't play well with the ownership transfer.



I apologize for my shallow Rust knowledge in advance.



pub struct ConsulKV 
pub Key: String,
pub Value: Option<String>


pub struct RawKV
pub key: String,
pub value: String


struct Location
ns: Vec<String>,


impl Location
fn path(&self) -> String
self.ns.join("/")


fn name(&self) -> String
self.ns.last().get_or_insert(&String::from(".")).clone()


fn base(&self) -> Location
match self.ns.first()
None => Location ns: vec![] ,
Some(head) => Location
ns: vec![head.clone()],
,



fn drop_base_mut(&mut self) -> &Location
self.ns.remove(0);
self



impl PartialEq for Location
fn eq(&self, other: &Location) -> bool
self.ns == other.ns



pub enum Node
KeyValue
path: Location,
name: String,
value: String,
,
Directory
path: Location,
nodes: Vec<Node>,
,


impl Node
pub fn new(r1: Vec<RawKV>) -> ResulT<Vec<Node>>
let raws = Node::preprocess(r1)?;
Ok(Node::process(raws))


fn preprocess(raw_kvs: Vec<RawKV>) -> ResulT<Vec<Node>> rkv

fn process(mut nodes: Vec<Node>) -> Vec<Node> n.path().base());
grouped
.into_iter()
.map(

fn drop_base_mut(&mut self) -> &Node
match self
Node::KeyValue path, .. =>
path.drop_base_mut();
self

Node::Directory path, .. =>
path.drop_base_mut();
self




fn path(&self) -> &Location
match self
Node::KeyValue path, .. => path,
Node::Directory path, .. => path,












share|improve this question









New contributor



RedDree is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






$endgroup$






















    3














    $begingroup$


    I have a piece of working code that takes some strings from Consul configuration exports, sanitizes them a little and converts them into valid json and/or hocon structures.



    While I am iterating over a vector of Nodes in the process function, I couldn't come up with a better solution than having to clone them. After inspecting some related APIs and looking for possible solutions, I understand (hopefully correctly) that it's a baked-in feature of Rust that you cannot move the ownership of the 'iteratee' to the result of the iteration.



    Probably, I have to re-write everything in order to optimize the performance, but I need to research more to understand what would be the most idiomatic way to write this in Rust.



    In the process I'm cloning the Vec's of Node's. I want to collect them as Node's, and not as &Node's, and this doesn't play well with the ownership transfer.



    I apologize for my shallow Rust knowledge in advance.



    pub struct ConsulKV 
    pub Key: String,
    pub Value: Option<String>


    pub struct RawKV
    pub key: String,
    pub value: String


    struct Location
    ns: Vec<String>,


    impl Location
    fn path(&self) -> String
    self.ns.join("/")


    fn name(&self) -> String
    self.ns.last().get_or_insert(&String::from(".")).clone()


    fn base(&self) -> Location
    match self.ns.first()
    None => Location ns: vec![] ,
    Some(head) => Location
    ns: vec![head.clone()],
    ,



    fn drop_base_mut(&mut self) -> &Location
    self.ns.remove(0);
    self



    impl PartialEq for Location
    fn eq(&self, other: &Location) -> bool
    self.ns == other.ns



    pub enum Node
    KeyValue
    path: Location,
    name: String,
    value: String,
    ,
    Directory
    path: Location,
    nodes: Vec<Node>,
    ,


    impl Node
    pub fn new(r1: Vec<RawKV>) -> ResulT<Vec<Node>>
    let raws = Node::preprocess(r1)?;
    Ok(Node::process(raws))


    fn preprocess(raw_kvs: Vec<RawKV>) -> ResulT<Vec<Node>> rkv

    fn process(mut nodes: Vec<Node>) -> Vec<Node> n.path().base());
    grouped
    .into_iter()
    .map(

    fn drop_base_mut(&mut self) -> &Node
    match self
    Node::KeyValue path, .. =>
    path.drop_base_mut();
    self

    Node::Directory path, .. =>
    path.drop_base_mut();
    self




    fn path(&self) -> &Location
    match self
    Node::KeyValue path, .. => path,
    Node::Directory path, .. => path,












    share|improve this question









    New contributor



    RedDree is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.






    $endgroup$


















      3












      3








      3





      $begingroup$


      I have a piece of working code that takes some strings from Consul configuration exports, sanitizes them a little and converts them into valid json and/or hocon structures.



      While I am iterating over a vector of Nodes in the process function, I couldn't come up with a better solution than having to clone them. After inspecting some related APIs and looking for possible solutions, I understand (hopefully correctly) that it's a baked-in feature of Rust that you cannot move the ownership of the 'iteratee' to the result of the iteration.



      Probably, I have to re-write everything in order to optimize the performance, but I need to research more to understand what would be the most idiomatic way to write this in Rust.



      In the process I'm cloning the Vec's of Node's. I want to collect them as Node's, and not as &Node's, and this doesn't play well with the ownership transfer.



      I apologize for my shallow Rust knowledge in advance.



      pub struct ConsulKV 
      pub Key: String,
      pub Value: Option<String>


      pub struct RawKV
      pub key: String,
      pub value: String


      struct Location
      ns: Vec<String>,


      impl Location
      fn path(&self) -> String
      self.ns.join("/")


      fn name(&self) -> String
      self.ns.last().get_or_insert(&String::from(".")).clone()


      fn base(&self) -> Location
      match self.ns.first()
      None => Location ns: vec![] ,
      Some(head) => Location
      ns: vec![head.clone()],
      ,



      fn drop_base_mut(&mut self) -> &Location
      self.ns.remove(0);
      self



      impl PartialEq for Location
      fn eq(&self, other: &Location) -> bool
      self.ns == other.ns



      pub enum Node
      KeyValue
      path: Location,
      name: String,
      value: String,
      ,
      Directory
      path: Location,
      nodes: Vec<Node>,
      ,


      impl Node
      pub fn new(r1: Vec<RawKV>) -> ResulT<Vec<Node>>
      let raws = Node::preprocess(r1)?;
      Ok(Node::process(raws))


      fn preprocess(raw_kvs: Vec<RawKV>) -> ResulT<Vec<Node>> rkv

      fn process(mut nodes: Vec<Node>) -> Vec<Node> n.path().base());
      grouped
      .into_iter()
      .map(

      fn drop_base_mut(&mut self) -> &Node
      match self
      Node::KeyValue path, .. =>
      path.drop_base_mut();
      self

      Node::Directory path, .. =>
      path.drop_base_mut();
      self




      fn path(&self) -> &Location
      match self
      Node::KeyValue path, .. => path,
      Node::Directory path, .. => path,












      share|improve this question









      New contributor



      RedDree is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      $endgroup$




      I have a piece of working code that takes some strings from Consul configuration exports, sanitizes them a little and converts them into valid json and/or hocon structures.



      While I am iterating over a vector of Nodes in the process function, I couldn't come up with a better solution than having to clone them. After inspecting some related APIs and looking for possible solutions, I understand (hopefully correctly) that it's a baked-in feature of Rust that you cannot move the ownership of the 'iteratee' to the result of the iteration.



      Probably, I have to re-write everything in order to optimize the performance, but I need to research more to understand what would be the most idiomatic way to write this in Rust.



      In the process I'm cloning the Vec's of Node's. I want to collect them as Node's, and not as &Node's, and this doesn't play well with the ownership transfer.



      I apologize for my shallow Rust knowledge in advance.



      pub struct ConsulKV 
      pub Key: String,
      pub Value: Option<String>


      pub struct RawKV
      pub key: String,
      pub value: String


      struct Location
      ns: Vec<String>,


      impl Location
      fn path(&self) -> String
      self.ns.join("/")


      fn name(&self) -> String
      self.ns.last().get_or_insert(&String::from(".")).clone()


      fn base(&self) -> Location
      match self.ns.first()
      None => Location ns: vec![] ,
      Some(head) => Location
      ns: vec![head.clone()],
      ,



      fn drop_base_mut(&mut self) -> &Location
      self.ns.remove(0);
      self



      impl PartialEq for Location
      fn eq(&self, other: &Location) -> bool
      self.ns == other.ns



      pub enum Node
      KeyValue
      path: Location,
      name: String,
      value: String,
      ,
      Directory
      path: Location,
      nodes: Vec<Node>,
      ,


      impl Node
      pub fn new(r1: Vec<RawKV>) -> ResulT<Vec<Node>>
      let raws = Node::preprocess(r1)?;
      Ok(Node::process(raws))


      fn preprocess(raw_kvs: Vec<RawKV>) -> ResulT<Vec<Node>> rkv

      fn process(mut nodes: Vec<Node>) -> Vec<Node> n.path().base());
      grouped
      .into_iter()
      .map(

      fn drop_base_mut(&mut self) -> &Node
      match self
      Node::KeyValue path, .. =>
      path.drop_base_mut();
      self

      Node::Directory path, .. =>
      path.drop_base_mut();
      self




      fn path(&self) -> &Location
      match self
      Node::KeyValue path, .. => path,
      Node::Directory path, .. => path,









      performance beginner rust configuration






      share|improve this question









      New contributor



      RedDree is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.










      share|improve this question









      New contributor



      RedDree is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.








      share|improve this question




      share|improve this question



      share|improve this question








      edited 7 hours ago









      200_success

      136k21 gold badges175 silver badges447 bronze badges




      136k21 gold badges175 silver badges447 bronze badges






      New contributor



      RedDree is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.








      asked 11 hours ago









      RedDreeRedDree

      164 bronze badges




      164 bronze badges




      New contributor



      RedDree is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.




      New contributor




      RedDree is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.

























          1 Answer
          1






          active

          oldest

          votes


















          3
















          $begingroup$

          You're doing multiple clone operations because of the types you've used. Due to the fact that consul's KV store is a tree, it does not really make that much sense to represent it as a set of nested Vecs. As I'm sure you found out, you're running into serious issues trying to figure out whether keys are inserted, what keys are inserted, and how to modify them without getting the borrow checker in a twist.



          I'd like to share with you a simpler implementation, one that sidesteps all the problems you've had entirely. Since we're dealing with a KV tree, we can and should take advantage of a HashMap for this - its type is absolutely ideal for what we are about to do. We're going to define two enum types, one for the keys, one for the value:



          #[derive(Eq, PartialEq, Hash, Debug)]
          pub enum Key
          Leaf(String),
          Branch(String)


          #[derive(Eq, PartialEq, Debug)]
          pub enum Node
          Leaf
          key: String,
          value: String
          ,
          Branch
          key: String,
          children: HashMap<Key, Node>




          We're going to then proceed through a little game of indirection to avoid some of the reference issues we might encounter...



          impl Node 
          fn insert_key(children: &mut HashMap<Key, Node>, key: String, value: String)
          match children.entry(Key::Leaf(key.clone()))
          Entry::Occupied(mut state) =>
          state.insert(Node::Leaf
          key: key,
          value: value
          );
          ,
          Entry::Vacant(state) =>

          state.insert(Node::Leaf
          key: key,
          value: value
          );



          fn branch(children: &mut HashMap<Key, Node>, key: String, remainder: Vec<String>, value: String)
          match children.entry(Key::Branch(key.clone()))
          Entry::Occupied(mut state) =>
          // We already have a branch of that name, we just
          // forward the call and move on
          state.get_mut().add_value(remainder, value)
          ,
          Entry::Vacant(state) =>
          // We need to create the node
          let mut node = Node::Branch
          key: key,
          children: HashMap::new()
          ;
          let status = node.add_value(remainder, value);
          state.insert(node);
          status

          ;

          pub fn get(&self, test: &Key) -> Option<&Node>
          match self
          Node::Branch
          key: _key,
          ref children
          => children.get(test),
          _ => None


          pub fn add_value(&mut self, mut path: Vec<String>, value: String)
          match path.len()
          0 => panic!("Path cannot be empty"),
          1 => Node::insert_key(contents, path.pop().unwrap(), value),
          _ => Node::branch(contents, path.pop().unwrap(), path, value)

          );




          And finally, we create a method to construct our tree:



          pub fn into_tree(collection: Vec<RawKV>) -> Node 
          // Create the root namespace
          println!("Creating nodes");
          let mut root_node = Node::Branch
          key: "/".to_string(),
          children: HashMap::new()
          ;

          for node in collection
          let mut path_elements:Vec<String> = node.key.split("/").map(

          root_node



          This is more efficient than your method in multiple respects:



          • Less allocations (I am not copying nodes unless I absolutely have to)

          • Less re-processing (no use of group_by, no partition, nothing but recursive tree access)

          • Clearer code

          Let me know what you think :-)






          share|improve this answer










          $endgroup$
















            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );







            RedDree is a new contributor. Be nice, and check out our Code of Conduct.









            draft saved

            draft discarded
















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f230267%2fsanitize-and-build-data-structure-from-consul-configuration%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown


























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            3
















            $begingroup$

            You're doing multiple clone operations because of the types you've used. Due to the fact that consul's KV store is a tree, it does not really make that much sense to represent it as a set of nested Vecs. As I'm sure you found out, you're running into serious issues trying to figure out whether keys are inserted, what keys are inserted, and how to modify them without getting the borrow checker in a twist.



            I'd like to share with you a simpler implementation, one that sidesteps all the problems you've had entirely. Since we're dealing with a KV tree, we can and should take advantage of a HashMap for this - its type is absolutely ideal for what we are about to do. We're going to define two enum types, one for the keys, one for the value:



            #[derive(Eq, PartialEq, Hash, Debug)]
            pub enum Key
            Leaf(String),
            Branch(String)


            #[derive(Eq, PartialEq, Debug)]
            pub enum Node
            Leaf
            key: String,
            value: String
            ,
            Branch
            key: String,
            children: HashMap<Key, Node>




            We're going to then proceed through a little game of indirection to avoid some of the reference issues we might encounter...



            impl Node 
            fn insert_key(children: &mut HashMap<Key, Node>, key: String, value: String)
            match children.entry(Key::Leaf(key.clone()))
            Entry::Occupied(mut state) =>
            state.insert(Node::Leaf
            key: key,
            value: value
            );
            ,
            Entry::Vacant(state) =>

            state.insert(Node::Leaf
            key: key,
            value: value
            );



            fn branch(children: &mut HashMap<Key, Node>, key: String, remainder: Vec<String>, value: String)
            match children.entry(Key::Branch(key.clone()))
            Entry::Occupied(mut state) =>
            // We already have a branch of that name, we just
            // forward the call and move on
            state.get_mut().add_value(remainder, value)
            ,
            Entry::Vacant(state) =>
            // We need to create the node
            let mut node = Node::Branch
            key: key,
            children: HashMap::new()
            ;
            let status = node.add_value(remainder, value);
            state.insert(node);
            status

            ;

            pub fn get(&self, test: &Key) -> Option<&Node>
            match self
            Node::Branch
            key: _key,
            ref children
            => children.get(test),
            _ => None


            pub fn add_value(&mut self, mut path: Vec<String>, value: String)
            match path.len()
            0 => panic!("Path cannot be empty"),
            1 => Node::insert_key(contents, path.pop().unwrap(), value),
            _ => Node::branch(contents, path.pop().unwrap(), path, value)

            );




            And finally, we create a method to construct our tree:



            pub fn into_tree(collection: Vec<RawKV>) -> Node 
            // Create the root namespace
            println!("Creating nodes");
            let mut root_node = Node::Branch
            key: "/".to_string(),
            children: HashMap::new()
            ;

            for node in collection
            let mut path_elements:Vec<String> = node.key.split("/").map(

            root_node



            This is more efficient than your method in multiple respects:



            • Less allocations (I am not copying nodes unless I absolutely have to)

            • Less re-processing (no use of group_by, no partition, nothing but recursive tree access)

            • Clearer code

            Let me know what you think :-)






            share|improve this answer










            $endgroup$



















              3
















              $begingroup$

              You're doing multiple clone operations because of the types you've used. Due to the fact that consul's KV store is a tree, it does not really make that much sense to represent it as a set of nested Vecs. As I'm sure you found out, you're running into serious issues trying to figure out whether keys are inserted, what keys are inserted, and how to modify them without getting the borrow checker in a twist.



              I'd like to share with you a simpler implementation, one that sidesteps all the problems you've had entirely. Since we're dealing with a KV tree, we can and should take advantage of a HashMap for this - its type is absolutely ideal for what we are about to do. We're going to define two enum types, one for the keys, one for the value:



              #[derive(Eq, PartialEq, Hash, Debug)]
              pub enum Key
              Leaf(String),
              Branch(String)


              #[derive(Eq, PartialEq, Debug)]
              pub enum Node
              Leaf
              key: String,
              value: String
              ,
              Branch
              key: String,
              children: HashMap<Key, Node>




              We're going to then proceed through a little game of indirection to avoid some of the reference issues we might encounter...



              impl Node 
              fn insert_key(children: &mut HashMap<Key, Node>, key: String, value: String)
              match children.entry(Key::Leaf(key.clone()))
              Entry::Occupied(mut state) =>
              state.insert(Node::Leaf
              key: key,
              value: value
              );
              ,
              Entry::Vacant(state) =>

              state.insert(Node::Leaf
              key: key,
              value: value
              );



              fn branch(children: &mut HashMap<Key, Node>, key: String, remainder: Vec<String>, value: String)
              match children.entry(Key::Branch(key.clone()))
              Entry::Occupied(mut state) =>
              // We already have a branch of that name, we just
              // forward the call and move on
              state.get_mut().add_value(remainder, value)
              ,
              Entry::Vacant(state) =>
              // We need to create the node
              let mut node = Node::Branch
              key: key,
              children: HashMap::new()
              ;
              let status = node.add_value(remainder, value);
              state.insert(node);
              status

              ;

              pub fn get(&self, test: &Key) -> Option<&Node>
              match self
              Node::Branch
              key: _key,
              ref children
              => children.get(test),
              _ => None


              pub fn add_value(&mut self, mut path: Vec<String>, value: String)
              match path.len()
              0 => panic!("Path cannot be empty"),
              1 => Node::insert_key(contents, path.pop().unwrap(), value),
              _ => Node::branch(contents, path.pop().unwrap(), path, value)

              );




              And finally, we create a method to construct our tree:



              pub fn into_tree(collection: Vec<RawKV>) -> Node 
              // Create the root namespace
              println!("Creating nodes");
              let mut root_node = Node::Branch
              key: "/".to_string(),
              children: HashMap::new()
              ;

              for node in collection
              let mut path_elements:Vec<String> = node.key.split("/").map(

              root_node



              This is more efficient than your method in multiple respects:



              • Less allocations (I am not copying nodes unless I absolutely have to)

              • Less re-processing (no use of group_by, no partition, nothing but recursive tree access)

              • Clearer code

              Let me know what you think :-)






              share|improve this answer










              $endgroup$

















                3














                3










                3







                $begingroup$

                You're doing multiple clone operations because of the types you've used. Due to the fact that consul's KV store is a tree, it does not really make that much sense to represent it as a set of nested Vecs. As I'm sure you found out, you're running into serious issues trying to figure out whether keys are inserted, what keys are inserted, and how to modify them without getting the borrow checker in a twist.



                I'd like to share with you a simpler implementation, one that sidesteps all the problems you've had entirely. Since we're dealing with a KV tree, we can and should take advantage of a HashMap for this - its type is absolutely ideal for what we are about to do. We're going to define two enum types, one for the keys, one for the value:



                #[derive(Eq, PartialEq, Hash, Debug)]
                pub enum Key
                Leaf(String),
                Branch(String)


                #[derive(Eq, PartialEq, Debug)]
                pub enum Node
                Leaf
                key: String,
                value: String
                ,
                Branch
                key: String,
                children: HashMap<Key, Node>




                We're going to then proceed through a little game of indirection to avoid some of the reference issues we might encounter...



                impl Node 
                fn insert_key(children: &mut HashMap<Key, Node>, key: String, value: String)
                match children.entry(Key::Leaf(key.clone()))
                Entry::Occupied(mut state) =>
                state.insert(Node::Leaf
                key: key,
                value: value
                );
                ,
                Entry::Vacant(state) =>

                state.insert(Node::Leaf
                key: key,
                value: value
                );



                fn branch(children: &mut HashMap<Key, Node>, key: String, remainder: Vec<String>, value: String)
                match children.entry(Key::Branch(key.clone()))
                Entry::Occupied(mut state) =>
                // We already have a branch of that name, we just
                // forward the call and move on
                state.get_mut().add_value(remainder, value)
                ,
                Entry::Vacant(state) =>
                // We need to create the node
                let mut node = Node::Branch
                key: key,
                children: HashMap::new()
                ;
                let status = node.add_value(remainder, value);
                state.insert(node);
                status

                ;

                pub fn get(&self, test: &Key) -> Option<&Node>
                match self
                Node::Branch
                key: _key,
                ref children
                => children.get(test),
                _ => None


                pub fn add_value(&mut self, mut path: Vec<String>, value: String)
                match path.len()
                0 => panic!("Path cannot be empty"),
                1 => Node::insert_key(contents, path.pop().unwrap(), value),
                _ => Node::branch(contents, path.pop().unwrap(), path, value)

                );




                And finally, we create a method to construct our tree:



                pub fn into_tree(collection: Vec<RawKV>) -> Node 
                // Create the root namespace
                println!("Creating nodes");
                let mut root_node = Node::Branch
                key: "/".to_string(),
                children: HashMap::new()
                ;

                for node in collection
                let mut path_elements:Vec<String> = node.key.split("/").map(

                root_node



                This is more efficient than your method in multiple respects:



                • Less allocations (I am not copying nodes unless I absolutely have to)

                • Less re-processing (no use of group_by, no partition, nothing but recursive tree access)

                • Clearer code

                Let me know what you think :-)






                share|improve this answer










                $endgroup$



                You're doing multiple clone operations because of the types you've used. Due to the fact that consul's KV store is a tree, it does not really make that much sense to represent it as a set of nested Vecs. As I'm sure you found out, you're running into serious issues trying to figure out whether keys are inserted, what keys are inserted, and how to modify them without getting the borrow checker in a twist.



                I'd like to share with you a simpler implementation, one that sidesteps all the problems you've had entirely. Since we're dealing with a KV tree, we can and should take advantage of a HashMap for this - its type is absolutely ideal for what we are about to do. We're going to define two enum types, one for the keys, one for the value:



                #[derive(Eq, PartialEq, Hash, Debug)]
                pub enum Key
                Leaf(String),
                Branch(String)


                #[derive(Eq, PartialEq, Debug)]
                pub enum Node
                Leaf
                key: String,
                value: String
                ,
                Branch
                key: String,
                children: HashMap<Key, Node>




                We're going to then proceed through a little game of indirection to avoid some of the reference issues we might encounter...



                impl Node 
                fn insert_key(children: &mut HashMap<Key, Node>, key: String, value: String)
                match children.entry(Key::Leaf(key.clone()))
                Entry::Occupied(mut state) =>
                state.insert(Node::Leaf
                key: key,
                value: value
                );
                ,
                Entry::Vacant(state) =>

                state.insert(Node::Leaf
                key: key,
                value: value
                );



                fn branch(children: &mut HashMap<Key, Node>, key: String, remainder: Vec<String>, value: String)
                match children.entry(Key::Branch(key.clone()))
                Entry::Occupied(mut state) =>
                // We already have a branch of that name, we just
                // forward the call and move on
                state.get_mut().add_value(remainder, value)
                ,
                Entry::Vacant(state) =>
                // We need to create the node
                let mut node = Node::Branch
                key: key,
                children: HashMap::new()
                ;
                let status = node.add_value(remainder, value);
                state.insert(node);
                status

                ;

                pub fn get(&self, test: &Key) -> Option<&Node>
                match self
                Node::Branch
                key: _key,
                ref children
                => children.get(test),
                _ => None


                pub fn add_value(&mut self, mut path: Vec<String>, value: String)
                match path.len()
                0 => panic!("Path cannot be empty"),
                1 => Node::insert_key(contents, path.pop().unwrap(), value),
                _ => Node::branch(contents, path.pop().unwrap(), path, value)

                );




                And finally, we create a method to construct our tree:



                pub fn into_tree(collection: Vec<RawKV>) -> Node 
                // Create the root namespace
                println!("Creating nodes");
                let mut root_node = Node::Branch
                key: "/".to_string(),
                children: HashMap::new()
                ;

                for node in collection
                let mut path_elements:Vec<String> = node.key.split("/").map(

                root_node



                This is more efficient than your method in multiple respects:



                • Less allocations (I am not copying nodes unless I absolutely have to)

                • Less re-processing (no use of group_by, no partition, nothing but recursive tree access)

                • Clearer code

                Let me know what you think :-)







                share|improve this answer













                share|improve this answer




                share|improve this answer



                share|improve this answer










                answered 6 hours ago









                Sébastien RenauldSébastien Renauld

                1312 bronze badges




                1312 bronze badges
























                    RedDree is a new contributor. Be nice, and check out our Code of Conduct.









                    draft saved

                    draft discarded

















                    RedDree is a new contributor. Be nice, and check out our Code of Conduct.












                    RedDree is a new contributor. Be nice, and check out our Code of Conduct.











                    RedDree is a new contributor. Be nice, and check out our Code of Conduct.














                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid


                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.

                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f230267%2fsanitize-and-build-data-structure-from-consul-configuration%23new-answer', 'question_page');

                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown









                    Popular posts from this blog

                    Invision Community Contents History See also References External links Navigation menuProprietaryinvisioncommunity.comIPS Community ForumsIPS Community Forumsthis blog entry"License Changes, IP.Board 3.4, and the Future""Interview -- Matt Mecham of Ibforums""CEO Invision Power Board, Matt Mecham Is a Liar, Thief!"IPB License Explanation 1.3, 1.3.1, 2.0, and 2.1ArchivedSecurity Fixes, Updates And Enhancements For IPB 1.3.1Archived"New Demo Accounts - Invision Power Services"the original"New Default Skin"the original"Invision Power Board 3.0.0 and Applications Released"the original"Archived copy"the original"Perpetual licenses being done away with""Release Notes - Invision Power Services""Introducing: IPS Community Suite 4!"Invision Community Release Notes

                    Canceling a color specificationRandomly assigning color to Graphics3D objects?Default color for Filling in Mathematica 9Coloring specific elements of sets with a prime modified order in an array plotHow to pick a color differing significantly from the colors already in a given color list?Detection of the text colorColor numbers based on their valueCan color schemes for use with ColorData include opacity specification?My dynamic color schemes

                    Ласкавець круглолистий Зміст Опис | Поширення | Галерея | Примітки | Посилання | Навігаційне меню58171138361-22960890446Bupleurum rotundifoliumEuro+Med PlantbasePlants of the World Online — Kew ScienceGermplasm Resources Information Network (GRIN)Ласкавецькн. VI : Літери Ком — Левиправивши або дописавши її