package core import ( "errors" "github.com/dop251/goja" ) type BufferObj struct { vm *goja.Runtime } func (b *BufferObj) From(v interface{}, EF string) *Buffer { var buffer []byte switch v := v.(type) { case string: if EF != "" { buffer = Convert(b.vm, v, EF, "bytes").([]byte) } else { buffer = []byte(v) } case []byte: if EF != "" { buffer = Convert(b.vm, v, EF, "bytes").([]byte) } else { buffer = v } case int: buffer = make([]byte, v) case int64: buffer = make([]byte, v) default: panic(b.vm.NewTypeError("invalid argument type")) } return &Buffer{ vm: b.vm, value: buffer, } } func (b *BufferObj) Alloc(v int) *Buffer { return &Buffer{ vm: b.vm, value: make([]byte, v), } } type Buffer struct { value []byte vm *goja.Runtime } func (b *Buffer) Length() int { return len(b.value) } func (b *Buffer) Write(value interface{}, offset int, length int) int { var buf []byte switch value := value.(type) { case string: buf = []byte(value) case []byte: buf = value default: panic(b.vm.NewTypeError("invalid argument type")) } if offset+length > len(b.value) { panic(b.vm.NewGoError(errors.New("out of range"))) } copy(b.value[offset:], buf[:length]) return len(b.value) } func (b *Buffer) ToString(EF string) interface{} { if EF != "" { return Convert(b.vm, b.value, "", EF) } return string(b.value) } func (b *Buffer) Slice(start int, end int) *Buffer { if start < 0 { start += len(b.value) } if end <= 0 { end += len(b.value) } if end > len(b.value) { end = len(b.value) } if start >= end || start >= len(b.value) { return nil } return &Buffer{ value: b.value[start:end], } } func (b *Buffer) Copy(target []byte, sourceStart int, targetStart int, sourceEnd int) int { if sourceStart < 0 { sourceStart += len(b.value) } if sourceEnd < 0 { sourceEnd += len(b.value) } if targetStart < 0 { targetStart += len(target) } if sourceEnd > len(b.value) { sourceEnd = len(b.value) } if sourceStart >= sourceEnd || sourceStart >= len(b.value) { return 0 } return copy(target[targetStart:], b.value[sourceStart:sourceEnd]) } func (b *Buffer) Join(sep []byte, buffers ...[]byte) []byte { var totalLen int for _, buf := range buffers { totalLen += len(buf) } if len(sep) > 0 && len(buffers) > 1 { totalLen += len(sep) * (len(buffers) - 1) } result := make([]byte, totalLen) offset := 0 for i, buf := range buffers { copy(result[offset:], buf) offset += len(buf) if i < len(buffers)-1 && len(sep) > 0 { copy(result[offset:], sep) offset += len(sep) } } return result } func bufferModule(vm *goja.Runtime, module *goja.Object) { o := module.Get("exports").(*goja.Object) o.Set("Buffer", &BufferObj{vm: vm}) }