Skip to content

Commit

Permalink
Initial commit to prepare for new architecture/design
Browse files Browse the repository at this point in the history
  • Loading branch information
Yuri6037 committed Jun 21, 2024
1 parent adf8ff6 commit 7483707
Show file tree
Hide file tree
Showing 13 changed files with 406 additions and 13 deletions.
64 changes: 64 additions & 0 deletions src/core/engine.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) 2024, BlockProject 3D
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of BlockProject 3D nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::num::NonZeroU32;
use std::sync::OnceLock;
use crate::core::field::FieldSet;
use crate::core::logger::Logger;
use crate::core::profiler::Profiler;
use crate::core::types::MetadataRef;

pub struct Engine {

}

impl Profiler for Engine {
fn section_register(&self, metadata: MetadataRef) -> NonZeroU32 {

Check warning on line 41 in src/core/engine.rs

View workflow job for this annotation

GitHub Actions / clippy

unused variable: `metadata`

warning: unused variable: `metadata` --> src/core/engine.rs:41:32 | 41 | fn section_register(&self, metadata: MetadataRef) -> NonZeroU32 { | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_metadata` | = note: `#[warn(unused_variables)]` on by default
todo!()
}

fn section_create(&self, id: NonZeroU32) {

Check warning on line 45 in src/core/engine.rs

View workflow job for this annotation

GitHub Actions / clippy

unused variable: `id`

warning: unused variable: `id` --> src/core/engine.rs:45:30 | 45 | fn section_create(&self, id: NonZeroU32) { | ^^ help: if this is intentional, prefix it with an underscore: `_id`
todo!()
}

fn section_follows(&self, id: NonZeroU32, follows: NonZeroU32) {

Check warning on line 49 in src/core/engine.rs

View workflow job for this annotation

GitHub Actions / clippy

unused variable: `follows`

warning: unused variable: `follows` --> src/core/engine.rs:49:47 | 49 | fn section_follows(&self, id: NonZeroU32, follows: NonZeroU32) { | ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_follows`

Check warning on line 49 in src/core/engine.rs

View workflow job for this annotation

GitHub Actions / clippy

unused variable: `id`

warning: unused variable: `id` --> src/core/engine.rs:49:31 | 49 | fn section_follows(&self, id: NonZeroU32, follows: NonZeroU32) { | ^^ help: if this is intentional, prefix it with an underscore: `_id`
todo!()
}

fn section_exit<F: FieldSet>(&self, id: NonZeroU32, start: u64, end: u64, fields: F) {

Check warning on line 53 in src/core/engine.rs

View workflow job for this annotation

GitHub Actions / clippy

unused variable: `fields`

warning: unused variable: `fields` --> src/core/engine.rs:53:79 | 53 | fn section_exit<F: FieldSet>(&self, id: NonZeroU32, start: u64, end: u64, fields: F) { | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_fields`

Check warning on line 53 in src/core/engine.rs

View workflow job for this annotation

GitHub Actions / clippy

unused variable: `end`

warning: unused variable: `end` --> src/core/engine.rs:53:69 | 53 | fn section_exit<F: FieldSet>(&self, id: NonZeroU32, start: u64, end: u64, fields: F) { | ^^^ help: if this is intentional, prefix it with an underscore: `_end`

Check warning on line 53 in src/core/engine.rs

View workflow job for this annotation

GitHub Actions / clippy

unused variable: `start`

warning: unused variable: `start` --> src/core/engine.rs:53:57 | 53 | fn section_exit<F: FieldSet>(&self, id: NonZeroU32, start: u64, end: u64, fields: F) { | ^^^^^ help: if this is intentional, prefix it with an underscore: `_start`

Check warning on line 53 in src/core/engine.rs

View workflow job for this annotation

GitHub Actions / clippy

unused variable: `id`

warning: unused variable: `id` --> src/core/engine.rs:53:41 | 53 | fn section_exit<F: FieldSet>(&self, id: NonZeroU32, start: u64, end: u64, fields: F) { | ^^ help: if this is intentional, prefix it with an underscore: `_id`
todo!()
}
}

impl Logger for Engine {
fn log_msg<F: FieldSet>(&self, metadata: MetadataRef, fields: F) {

Check warning on line 59 in src/core/engine.rs

View workflow job for this annotation

GitHub Actions / clippy

unused variable: `fields`

warning: unused variable: `fields` --> src/core/engine.rs:59:59 | 59 | fn log_msg<F: FieldSet>(&self, metadata: MetadataRef, fields: F) { | ^^^^^^ help: if this is intentional, prefix it with an underscore: `_fields`

Check warning on line 59 in src/core/engine.rs

View workflow job for this annotation

GitHub Actions / clippy

unused variable: `metadata`

warning: unused variable: `metadata` --> src/core/engine.rs:59:36 | 59 | fn log_msg<F: FieldSet>(&self, metadata: MetadataRef, fields: F) { | ^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_metadata`
todo!()
}
}

pub static ENGINE: OnceLock<Engine> = OnceLock::new();
57 changes: 57 additions & 0 deletions src/core/field.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) 2024, BlockProject 3D
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of BlockProject 3D nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::fmt::Debug;

pub trait Visitor {
fn visit_int(&mut self, name: &str, value: i64) {
self.visit_debug(name, value);
}

fn visit_uint(&mut self, name: &str, value: u64) {
self.visit_debug(name, value);
}

fn visit_float(&mut self, name: &str, value: f32) {
self.visit_debug(name, value);
}

fn visit_double(&mut self, name: &str, value: f64) {
self.visit_debug(name, value);
}

fn visit_string(&mut self, name: &str, value: &str) {
self.visit_debug(name, value);
}

fn visit_debug<T: Debug>(&mut self, name: &str, debug: T);
}

pub trait FieldSet {
fn record<V: Visitor>(self, visitor: &mut V);
}
34 changes: 34 additions & 0 deletions src/core/logger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) 2024, BlockProject 3D
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of BlockProject 3D nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use crate::core::field::FieldSet;
use crate::core::types::MetadataRef;

pub trait Logger {
fn log_msg<F: FieldSet>(&self, metadata: MetadataRef, fields: F);
}
29 changes: 29 additions & 0 deletions src/core/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2024, BlockProject 3D
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of BlockProject 3D nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


38 changes: 38 additions & 0 deletions src/core/metadata.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) 2024, BlockProject 3D
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of BlockProject 3D nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use crate::core::types::{Level};

pub trait Metadata {
fn name() -> &'static str;
fn target() -> &'static str;
fn module_path() -> Option<&'static str>;
fn file() -> Option<&'static str>;
fn line() -> Option<u32>;
fn level() -> Level;
}
35 changes: 35 additions & 0 deletions src/core/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) 2024, BlockProject 3D
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of BlockProject 3D nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

pub mod types;
mod profiler;
mod logger;
mod metadata;
mod field;
mod macros;
mod engine;
81 changes: 81 additions & 0 deletions src/core/profiler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright (c) 2024, BlockProject 3D
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of BlockProject 3D nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::mem::ManuallyDrop;
use std::num::NonZeroU32;
use std::time::Instant;
use crate::core::engine::ENGINE;
use crate::core::field::FieldSet;
use crate::core::types::{Metadata, MetadataRef};

thread_local! {
static CUR_TIME: Instant = Instant::now();
}

pub struct EnteredSection<F: FieldSet> {
id: NonZeroU32,
start: u64,
fields: ManuallyDrop<F>
}

impl<F: FieldSet> Drop for EnteredSection<F> {
fn drop(&mut self) {
let engine = unsafe { ENGINE.get().unwrap_unchecked() };
let end = CUR_TIME.with(|v| v.elapsed().as_nanos() as _);
let fields = unsafe { ManuallyDrop::into_inner(std::ptr::read(&self.fields)) };
engine.section_exit(self.id, self.start, end, fields);
}
}

pub struct ProfilerSection {
id: Option<NonZeroU32>
}

impl ProfilerSection {
pub fn new(metadata: &'static Metadata) -> Self {
let id = ENGINE.get().map(|engine| engine.section_register(MetadataRef::Borrowed(metadata)));
Self {
id,
}
}

pub fn enter<F: FieldSet>(&self, fields: F) -> Option<EnteredSection<F>> {
self.id.map(|id| EnteredSection {
id,
start: CUR_TIME.with(|v| v.elapsed().as_nanos() as _),
fields: ManuallyDrop::new(fields)
})
}
}

pub trait Profiler {
fn section_register(&self, metadata: MetadataRef) -> NonZeroU32;
fn section_create(&self, id: NonZeroU32);
fn section_follows(&self, id: NonZeroU32, follows: NonZeroU32);
fn section_exit<F: FieldSet>(&self, id: NonZeroU32, start: u64, end: u64, fields: F);
}
54 changes: 54 additions & 0 deletions src/core/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (c) 2024, BlockProject 3D
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of BlockProject 3D nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::fmt::Debug;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Copy, Clone, Debug)]
#[repr(u8)]
pub enum Level {
Trace = 0,
Debug = 1,
Info = 2,
Warning = 3,
Error = 4,
}

pub struct Metadata {
pub name: &'static str,
pub target: &'static str,
pub module_path: Option<&'static str>,
pub file: Option<&'static str>,
pub line: Option<u32>,
pub level: Level
}

pub enum MetadataRef {
Borrowed(&'static Metadata),
Owned(Metadata)
}
Loading

0 comments on commit 7483707

Please sign in to comment.