#![allow(non_snake_case)]
#![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] #![allow(dead_code)]
use core::any::Any;
use crate::ported::crt::{ColorElements as CE, ColorScheme};
use crate::ported::machine::Machine;
use crate::ported::object::{Object, ObjectClass};
use crate::ported::process::{
spaceship_nullstr, Process, ProcessClass, Process_class, Process_compareByKey_Base,
Process_compareByParent, Process_init, Process_rowGetSortKey, Process_rowIsHighlighted,
Process_rowIsVisible, Process_writeField,
};
use crate::ported::richstring::{RichString, RichString_appendWide};
use crate::ported::row::{spaceship_number, Row, RowClass, Row_pidDigits, Row_printLeftAlignedField};
use crate::ported::settings::RowField;
use std::os::raw::c_void;
use std::sync::atomic::Ordering;
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(C)]
pub enum FreeBSDSchedClass {
SCHEDCLASS_UNKNOWN = 0,
SCHEDCLASS_INTR_THREAD,
SCHEDCLASS_REALTIME,
SCHEDCLASS_TIMESHARE,
SCHEDCLASS_IDLE,
}
#[repr(C)]
pub struct FreeBSDProcess {
pub super_: Process,
pub jid: i32,
pub jname: Option<String>,
pub emul: Option<String>,
pub sched_class: FreeBSDSchedClass,
}
const FreeBSD_schedclassChars: [u8; 5] = [b'?', b'-', b'r', b' ', b'i'];
const JID: RowField = 100;
const JAIL: RowField = 101;
const EMULATION: RowField = 102;
const SCHEDCLASS: RowField = 103;
pub static FreeBSDProcess_class: ProcessClass = ProcessClass {
super_: RowClass {
super_: ObjectClass {
extends: Some(&Process_class.super_.super_),
},
isHighlighted: Some(Process_rowIsHighlighted),
isVisible: Some(Process_rowIsVisible),
writeField: Some(FreeBSDProcess_rowWriteField),
matchesFilter: None,
sortKeyString: Some(Process_rowGetSortKey),
compareByParent: Some(Process_compareByParent),
},
compareByKey: Some(FreeBSDProcess_compareByKey),
};
impl Object for FreeBSDProcess {
fn klass(&self) -> &'static ObjectClass {
&FreeBSDProcess_class.super_.super_
}
fn row_class(&self) -> Option<&'static RowClass> {
Some(&FreeBSDProcess_class.super_)
}
fn process_class(&self) -> Option<&'static ProcessClass> {
Some(&FreeBSDProcess_class)
}
fn display(&self, out: &mut RichString) {
crate::ported::row::Row_display(self, out)
}
fn compare(&self, other: &dyn Object) -> i32 {
crate::ported::process::Process_compare(self, other)
}
fn as_row(&self) -> Option<&Row> {
Some(&self.super_.super_)
}
fn as_row_mut(&mut self) -> Option<&mut Row> {
Some(&mut self.super_.super_)
}
fn as_process(&self) -> Option<&Process> {
Some(&self.super_)
}
fn as_process_mut(&mut self) -> Option<&mut Process> {
Some(&mut self.super_)
}
}
pub fn FreeBSDProcess_new(machine: *const Machine) -> Box<FreeBSDProcess> {
let mut this = Box::new(FreeBSDProcess {
super_: Process::default(),
jid: 0,
jname: None,
emul: None,
sched_class: FreeBSDSchedClass::SCHEDCLASS_UNKNOWN,
});
Process_init(&mut this.super_, machine as *const c_void);
this
}
pub fn Process_delete() {
todo!("port of FreeBSDProcess.c:69 — pure free() teardown; Rust Drop handles it")
}
pub fn FreeBSDProcess_rowWriteField(super_: &dyn Object, str: &mut RichString, field: RowField) {
let fp = (super_ as &dyn Any)
.downcast_ref::<FreeBSDProcess>()
.expect("FreeBSDProcess_rowWriteField: row is not a FreeBSDProcess");
let scheme = ColorScheme::active();
let attr = CE::DEFAULT_COLOR.packed(scheme);
let buffer: String;
match field {
JID => {
let digits = Row_pidDigits.load(Ordering::Relaxed) as usize;
buffer = format!("{:>digits$} ", fp.jid);
}
JAIL => {
let name = fp.jname.as_deref().unwrap_or("N/A");
Row_printLeftAlignedField(str, attr, name.as_bytes(), 11);
return;
}
EMULATION => {
let name = fp.emul.as_deref().unwrap_or("N/A");
Row_printLeftAlignedField(str, attr, name.as_bytes(), 16);
return;
}
SCHEDCLASS => {
let sched_class = FreeBSD_schedclassChars[fp.sched_class as usize];
buffer = format!(" {}", sched_class as char);
}
_ => {
Process_writeField(&fp.super_, str, field);
return;
}
}
RichString_appendWide(str, attr, buffer.as_bytes());
}
pub fn FreeBSDProcess_compareByKey(v1: &dyn Object, v2: &dyn Object, key: RowField) -> i32 {
let p1 = (v1 as &dyn Any)
.downcast_ref::<FreeBSDProcess>()
.expect("FreeBSDProcess_compareByKey: v1 is not a FreeBSDProcess");
let p2 = (v2 as &dyn Any)
.downcast_ref::<FreeBSDProcess>()
.expect("FreeBSDProcess_compareByKey: v2 is not a FreeBSDProcess");
match key {
JID => spaceship_number!(p1.jid, p2.jid),
JAIL => spaceship_nullstr!(
p1.jname.as_deref().map(str::as_bytes),
p2.jname.as_deref().map(str::as_bytes)
),
EMULATION => spaceship_nullstr!(
p1.emul.as_deref().map(str::as_bytes),
p2.emul.as_deref().map(str::as_bytes)
),
SCHEDCLASS => spaceship_number!(p1.sched_class as i32, p2.sched_class as i32),
_ => Process_compareByKey_Base(&p1.super_, &p2.super_, key),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn super_is_at_offset_zero_for_sound_downcast() {
assert_eq!(core::mem::offset_of!(FreeBSDProcess, super_), 0);
let host = 0xF00D as *const Machine;
let fp = FreeBSDProcess_new(host);
let base: *const Process = &fp.super_;
let back = base as *const FreeBSDProcess;
assert_eq!(back, &*fp as *const FreeBSDProcess);
}
#[test]
fn new_sets_freebsd_defaults() {
let host = 0xF00D as *const Machine;
let fp = FreeBSDProcess_new(host);
assert_eq!(fp.jid, 0);
assert!(fp.jname.is_none());
assert!(fp.emul.is_none());
assert!(fp.sched_class == FreeBSDSchedClass::SCHEDCLASS_UNKNOWN);
assert_eq!(fp.super_.super_.host, host as *const c_void);
}
#[test]
fn schedclass_chars_match_c_designated_initializers() {
assert_eq!(
FreeBSD_schedclassChars[FreeBSDSchedClass::SCHEDCLASS_UNKNOWN as usize],
b'?'
);
assert_eq!(
FreeBSD_schedclassChars[FreeBSDSchedClass::SCHEDCLASS_INTR_THREAD as usize],
b'-'
);
assert_eq!(
FreeBSD_schedclassChars[FreeBSDSchedClass::SCHEDCLASS_REALTIME as usize],
b'r'
);
assert_eq!(
FreeBSD_schedclassChars[FreeBSDSchedClass::SCHEDCLASS_TIMESHARE as usize],
b' '
);
assert_eq!(
FreeBSD_schedclassChars[FreeBSDSchedClass::SCHEDCLASS_IDLE as usize],
b'i'
);
}
#[test]
fn compareByKey_orders_platform_fields() {
let host = 0xF00D as *const Machine;
let mut a = FreeBSDProcess_new(host);
let mut b = FreeBSDProcess_new(host);
a.jid = 3;
b.jid = 7;
assert!(FreeBSDProcess_compareByKey(&*a, &*b, JID) < 0);
a.jname = Some("alpha".into());
b.jname = Some("beta".into());
assert!(FreeBSDProcess_compareByKey(&*a, &*b, JAIL) < 0);
a.sched_class = FreeBSDSchedClass::SCHEDCLASS_IDLE;
b.sched_class = FreeBSDSchedClass::SCHEDCLASS_REALTIME;
assert!(FreeBSDProcess_compareByKey(&*a, &*b, SCHEDCLASS) > 0);
}
}