How to add items to the tree correctly?

I can't figure out how to add a new item to the tree.

use serde::{Serialize, Deserialize};
use std::collections::{HashMap, BTreeMap};
use async_std::sync::{Arc};
use uuid::Uuid;
use tokio::sync::Mutex;
// Структура для одного логу
#[derive(Serialize, Deserialize, Clone, Debug)]
struct Log {
    number: u64,
    data: String,
    message: String,
}

// Оновлена структура для зберігання логів, яка тепер може включати вкладені групи
#[derive(Serialize, Deserialize, Clone, Debug)]
enum LogItem {
    SingleLog(Log),
    LogGroup(BTreeMap<String, Vec<LogItem>>),
}

// Оновлена структура для зберігання всіх логів і синхронізації
#[derive(Clone, Debug)]
struct LogManager {
    logs: Arc<Mutex<BTreeMap<String, Vec<LogItem>>>>, // Оновлено для вкладених груп
    global_counter: Arc<Mutex<u64>>,
}

impl LogManager {
    // Функція для ініціалізації нового LogManager
    async fn new() -> Self {
        Self {
            logs: Arc::new(Mutex::new(BTreeMap::new())),
            global_counter: Arc::new(Mutex::new(0)),
        }
    }

    // Асинхронна функція для додавання нового логу
    async fn add_log(&self, group_path: Vec<String>, data: String, message: String) {
        let mut counter = self.global_counter.lock().await;
        let mut logs = self.logs.lock().await;

        let log = LogItem::SingleLog(Log {
            number: *counter,
            data,
            message,
        });

        let mut current_group = logs;
        for group_name in group_path {
            let group = current_group.entry(group_name).or_insert_with(|| Vec::new());
            if let Some(LogItem::LogGroup(sub_group)) = group.last_mut() {
                current_group = sub_group;
            } else {
                let new_group = LogItem::LogGroup(BTreeMap::new());
                group.push(new_group);
                if let LogItem::LogGroup(sub_group) = group.last_mut().unwrap() {
                    current_group = sub_group;
                }
            }
        }
        current_group.entry(group_path.last().unwrap().to_string()).or_insert_with(Vec::new).push(log);
        *counter += 1;
    }

    // Функція для отримання всіх логів в JSON форматі
    async fn get_logs_json(&self) -> String {
        let logs = self.logs.lock().await;
        serde_json::to_string(&*logs).unwrap()
    }
}

My error:

error[E0308]: mismatched types
  --> src/logger.rs:52:33
   |
48 |         let mut current_group = logs;
   |                                 ---- expected due to this value
...
52 |                 current_group = sub_group;
   |                                 ^^^^^^^^^ expected `MutexGuard<'_, BTreeMap<..., ...>>`, found `&mut BTreeMap<String, Vec<LogItem>>`
   |
   = note:         expected struct `tokio::sync::MutexGuard<'_, BTreeMap<_, _>, >`
           found mutable reference `&mut BTreeMap<_, _>`

I can't speak as to the logic, but this gets rid of the errors.

        // Save this before consuming `group_path` with the `for` loop
        let last = group_path.last().unwrap().to_string();
        // Get a `&mut _` from the `MutexGuard`
        let mut current_group = &mut *logs;
        for group_name in group_path {
            let group = current_group.entry(group_name).or_insert_with(|| Vec::new());
            if let Some(LogItem::LogGroup(sub_group)) = group.last_mut() {
            } else {
                let new_group = LogItem::LogGroup(BTreeMap::new());
                group.push(new_group);
            }
            // Do one unconditional reassignment here
            current_group = if let Some(LogItem::LogGroup(sub_group)) = group.last_mut() {
                sub_group
            } else {
                unreachable!()
            };
        }
        // This line is why we needed `last`
        current_group.entry(last).or_insert_with(Vec::new).push(log);
1 Like

Thank you very much

fixed the logic now everything works correctly

pub async fn add_log(&self, group_path: Vec<String>, data: String, message: String) {
        let mut counter = self.global_counter.lock().await;
        let mut logs = self.logs.lock().await;

        let log = LogItem::SingleLog(Log {
            number: *counter,
            data,
            message,
        });

        let last = group_path.last().unwrap().to_string();
        // Get a `&mut _` from the `MutexGuard`
        let mut current_group = &mut *logs;
        for i in 0..group_path.len()-1 {
            let group = current_group.entry(group_path[i].clone()).or_insert_with(|| Vec::new());
            if let Some(LogItem::LogGroup(sub_group)) = group.last_mut() {
            } else {
                let new_group = LogItem::LogGroup(BTreeMap::new());
                group.push(new_group);
            };
            current_group = if let Some(LogItem::LogGroup(sub_group)) = group.last_mut() {
                sub_group
            } else {
                unreachable!()
                
            };
            
        }
        current_group.entry(last).or_insert_with(Vec::new).push(log);
        *counter += 1;

    }

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.