Skip to content

Commit

Permalink
feat(utils): 新增 bytes
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Jul 9, 2023
1 parent 1f15d13 commit 7ea6ae7
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 0 deletions.
86 changes: 86 additions & 0 deletions src/utils/bytes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { bytes } from './bytes'

describe('bytes', () => {
test('ok', () => {
expect(bytes(1024)).toBe(1024)
expect(bytes('1024B')).toBe(1024)
expect(bytes(2048, 'B')).toBe(2048)

expect(bytes('1KB')).toBe(1024)
expect(bytes(1, 'KB')).toBe(1024)
expect(bytes(2, 'KB')).toBe(2048)

expect(bytes('1MB')).toBe(1048576)
expect(bytes(1, 'MB')).toBe(1048576)
expect(bytes(1024, 'KB')).toBe(1048576)

expect(bytes('1GB')).toBe(1073741824)
expect(bytes(1, 'GB')).toBe(1073741824)
expect(bytes('1024MB')).toBe(1073741824)

expect(bytes('1TB')).toBe(1099511627776)
expect(bytes(1, 'TB')).toBe(1099511627776)
expect(bytes('1024GB')).toBe(1099511627776)

expect(bytes('1PB')).toBe(1125899906842624)
expect(bytes(1, 'PB')).toBe(1125899906842624)
expect(bytes('1024TB')).toBe(1125899906842624)
})

test('非法值应报错', () => {
expect(function () {
// @ts-expect-error - We expect this to throw.
bytes('')
}).toThrowError()
expect(function () {
// @ts-expect-error - We expect this to throw.
bytes(undefined)
}).toThrowError()
expect(function () {
// @ts-expect-error - We expect this to throw.
bytes(null)
}).toThrowError()
expect(function () {
// @ts-expect-error - We expect this to throw.
bytes([])
}).toThrowError()
expect(function () {
// @ts-expect-error - We expect this to throw.
bytes({})
}).toThrowError()
expect(function () {
bytes(NaN)
}).toThrowError()
expect(function () {
bytes(Infinity)
}).toThrowError()
expect(function () {
bytes(-Infinity)
}).toThrowError()
expect(function () {
bytes(
1,
// @ts-expect-error - We expect this to throw.
'BB',
)
}).toThrowError()
expect(function () {
bytes(
// @ts-expect-error - We expect this to throw.
'1BB',
)
}).toThrowError()
expect(function () {
bytes(
1,
// @ts-expect-error - We expect this to throw.
{},
)
}).toThrowError()
})

test('小数正常', () => {
expect(bytes('1.1B')).toBe(1.1)
expect(bytes(1.1, 'B')).toBe(1.1)
})
})
68 changes: 68 additions & 0 deletions src/utils/bytes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const _b = 1
const _kb = _b * 1024
const _mb = _kb * 1024
const _gb = _mb * 1024
const _tb = _gb * 1024
const _pb = _tb * 1024

export type BytesUnit = 'PB' | 'TB' | 'GB' | 'MB' | 'KB' | 'B'
export type BytesNumberValue = number
export type BytesStringValue = `${number}${BytesUnit}`
export type BytesValue = BytesNumberValue | BytesStringValue

const unitToBytes: Record<BytesUnit, number> = Object.create({
PB: _pb,
TB: _tb,
GB: _gb,
MB: _mb,
KB: _kb,
B: _b,
})

const re = /^(\d+(?:\.\d+)?)(PB|TB|GB|MB|KB|B)$/

/**
* 获取字节值。
*
* @param value 值
* @param unit 单位
*/
export function bytes(value: number, unit: BytesUnit): number
/**
* 获取字节值。
*
* @param value 值
*/
export function bytes(value: BytesValue): number
export function bytes(value: BytesValue, unit?: BytesUnit): number {
let bytesValue!: number

if (typeof value === 'string' && value.length > 0) {
const match = re.exec(value)
if (!match) {
throw new TypeError(`value 值非法: value=${JSON.stringify(value)}`)
}
const v = parseFloat(match[1])
const u: BytesUnit = match[2] as any
const t = unitToBytes[u]
bytesValue = v * t
} else if (typeof value === 'number' && isFinite(value)) {
if (unit != null) {
if (typeof unit === 'string') {
const t = unitToBytes[unit]
if (!t) {
throw new TypeError(`unit 值非法: unit=${JSON.stringify(unit)}`)
}
bytesValue = value * t
} else {
throw new TypeError('unit 必须是一个字符串')
}
} else {
bytesValue = value
}
} else {
throw new TypeError('value 必须是字符串或数字')
}

return bytesValue
}
2 changes: 2 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export * from './asyncLimit'
export * from './asyncMemoize'
export * from './base64'
export * from './bindEvent'
export * from './bytes'
export * from './Calculator'
export * from './cartesianProduct'
export * from './characterToCodepoint'
Expand Down Expand Up @@ -70,6 +71,7 @@ export * from './makeEnum'
export * from './md5'
export * from './MiniProgramUrl'
export * from './move'
export * from './ms'
export * from './omitStrict'
export * from './onceMeanwhile'
export * from './parseDataUrl'
Expand Down

0 comments on commit 7ea6ae7

Please sign in to comment.