import { _, RestOfLine, Newline, NumberValue, SeparatedNumberValue, BytesValue } from "../primitives" import { Header } from "../shared" { const matchValue = require("match-value"); } RootInfo = header:Header infoSection:InfoSection Newline* { return { ...header, fields: infoSection } }; InfoSection 'information section' = "=== START OF INFORMATION SECTION ===" Newline fields:(InfoField+) { return fields.filter((field) => field != null); } InfoField 'information field' = InfoFieldSimple / InfoFieldIgnored / InfoFieldSize / InfoFieldRPM / InfoFieldSectorSizes / InfoFieldBoolean / InfoFieldUnknown InfoFieldSimpleKey = "Device Model" { return "model"; } / "Model Number" { return "model"; } / "Model Family" { return "modelFamily"; } / "Serial Number" { return "serialNumber"; } / "LU WWN Device Id" { return "wwn"; } / "Firmware Version" { return "firmwareVersion"; } / "Form Factor" { return "formFactor"; } / "ATA Version is" { return "ataVersion"; } / "SATA Version is" { return "sataVersion"; } InfoFieldSimple = key:InfoFieldSimpleKey ":" _ value:RestOfLine { return { key: key, value: value }; } InfoFieldUnknown = key:$[^:]+ ":" _ RestOfLine { console.warn(`Encountered unrecognized SMART info key: ${key}`); return null; } InfoFieldIgnoredKey = "Device is" / "Local Time is" InfoFieldIgnored = key:InfoFieldIgnoredKey ":" _ RestOfLine { return null; } / "SMART support is:" _ ("Available" / "Unavailable") RestOfLine { // We don't actually care about this entry, but have to specify its possible values explicitly, to distinguish it from the entry we *do* care about that (annoyingly) uses the same key; see InfoFieldBoolean return null; } InfoFieldSize // NOTE: We don't actually care about the human-friendly display size after the 'bytes' specifier, hence the RestOfLine = InfoFieldSizeKey _ value:SeparatedNumberValue _ "bytes"? _ RestOfLine { return { key: "size", value: B(value) }; } InfoFieldSizeKey = "User Capacity:" / "Total NVM Capacity:" InfoFieldRPM = "Rotation Rate:" _ value:NumberValue _ "rpm" Newline { return { key: "rpm", value: value }; } InfoFieldSectorSizes = "Sector Sizes:" _ logicalSize:BytesValue _ "bytes logical," _ physicalSize:BytesValue _ "bytes physical" Newline { return { key: "sectorSizes", value: { logical: logicalSize, physical: physicalSize } }; } InfoFieldBooleanKey = "SMART support is" { return "smartEnabled"; } InfoFieldBoolean = key:InfoFieldBooleanKey ":" _ value:RestOfLine { return { key: key, value: matchValue(value, { Enabled: true, Disabled: false }) }; }