// Copyright 2025 foyer Project Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use bytes::Bytes;
use criterion::Criterion;

use super::{decode, encode, K, M};

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct VecU8ValueSerde(Vec<u8>);

impl VecU8ValueSerde {
    pub fn create(size: usize) -> Self {
        let mut v = vec![0; size];
        rand::fill(&mut v[..]);
        Self(v)
    }
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct VecU8ValueSerdeBytes(#[serde(with = "serde_bytes")] Vec<u8>);

impl VecU8ValueSerdeBytes {
    pub fn create(size: usize) -> Self {
        let mut v = vec![0; size];
        rand::fill(&mut v[..]);
        Self(v)
    }
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct BytesValueSerde(Bytes);

impl BytesValueSerde {
    pub fn create(size: usize) -> Self {
        let mut v = vec![0; size];
        rand::fill(&mut v[..]);
        Self(Bytes::from(v))
    }
}

pub fn bench_encode(c: &mut Criterion) {
    for (s, size) in [("64K", 64 * K), ("4M", 4 * M)] {
        c.bench_function(&format!("Vec<u8> value serde encode - {s}"), |b| {
            encode(b, VecU8ValueSerde::create(size), size);
        });
        c.bench_function(&format!("Vec<u8> value serde_bytes encode - {s}"), |b| {
            encode(b, VecU8ValueSerdeBytes::create(size), size);
        });
        c.bench_function(&format!("Bytes value serde encode - {s}"), |b| {
            encode(b, BytesValueSerde::create(size), size);
        });
    }
}

pub fn bench_decode(c: &mut Criterion) {
    for (s, size) in [("64K", 64 * K), ("4M", 4 * M)] {
        c.bench_function(&format!("Vec<u8> value serde decode - {s}"), |b| {
            decode(b, VecU8ValueSerde::create(size), size);
        });
        c.bench_function(&format!("Vec<u8> value serde_bytes decode - {s}"), |b| {
            decode(b, VecU8ValueSerdeBytes::create(size), size);
        });
        c.bench_function(&format!("Bytes value serde decode - {s}"), |b| {
            decode(b, BytesValueSerde::create(size), size);
        });
    }
}
