Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert go to v #19537

Open
2 tasks
emma-eva opened this issue Oct 9, 2023 · 14 comments
Open
2 tasks

Convert go to v #19537

emma-eva opened this issue Oct 9, 2023 · 14 comments

Comments

@emma-eva
Copy link

emma-eva commented Oct 9, 2023

Describe the feature

Convert this go code to v code:

package main

import (
	"errors"
	"io"
	"math"
	"reflect"
	"sync"
	"fmt"
	"strings"
)


type ByteOrder interface {
	Uint16([]byte) uint16
	Uint32([]byte) uint32
	Uint64([]byte) uint64
}

var LittleEndian littleEndian
type littleEndian struct{}

func (littleEndian) Uint16(b []byte) uint16 {
	return uint16(b[0]) | uint16(b[1])<<8
}

func (littleEndian) Uint32(b []byte) uint32 {
	return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}

func (littleEndian) Uint64(b []byte) uint64 {
	return uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
		uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
}

func Read(r io.Reader, order ByteOrder, data interface{}) error {
	if n := intDataSize(data); n != 0 {
		bs := make([]byte, n)
		if _, err := io.ReadFull(r, bs); err != nil {
			return err
		}
		switch data := data.(type) {
		case *bool:
			*data = bs[0] != 0
		case *int8:
			*data = int8(bs[0])
		case *uint8:
			*data = bs[0]
		case *int16:
			*data = int16(order.Uint16(bs))
		case *uint16:
			*data = order.Uint16(bs)
		case *int32:
			*data = int32(order.Uint32(bs))
		case *uint32:
			*data = order.Uint32(bs)
		case *int64:
			*data = int64(order.Uint64(bs))
		case *uint64:
			*data = order.Uint64(bs)
		case *float32:
			*data = math.Float32frombits(order.Uint32(bs))
		case *float64:
			*data = math.Float64frombits(order.Uint64(bs))
		case []bool:
			for i, x := range bs {
				data[i] = x != 0
			}
		case []int8:
			for i, x := range bs {
				data[i] = int8(x)
			}
		case []uint8:
			copy(data, bs)
		case []int16:
			for i := range data {
				data[i] = int16(order.Uint16(bs[2*i:]))
			}
		case []uint16:
			for i := range data {
				data[i] = order.Uint16(bs[2*i:])
			}
		case []int32:
			for i := range data {
				data[i] = int32(order.Uint32(bs[4*i:]))
			}
		case []uint32:
			for i := range data {
				data[i] = order.Uint32(bs[4*i:])
			}
		case []int64:
			for i := range data {
				data[i] = int64(order.Uint64(bs[8*i:]))
			}
		case []uint64:
			for i := range data {
				data[i] = order.Uint64(bs[8*i:])
			}
		case []float32:
			for i := range data {
				data[i] = math.Float32frombits(order.Uint32(bs[4*i:]))
			}
		case []float64:
			for i := range data {
				data[i] = math.Float64frombits(order.Uint64(bs[8*i:]))
			}
		default:
			n = 0
		}
		if n != 0 {
			return nil
		}
	}

	v := reflect.ValueOf(data)
	size := -1
	switch v.Kind() {
		case reflect.Pointer:
			v = v.Elem()
			size = dataSize(v)
		case reflect.Slice:
			size = dataSize(v)
	}
	if size < 0 {
		return errors.New("Read: invalid type " + reflect.TypeOf(data).String())
	}
	d := &decoder{order: order, buf: make([]byte, size)}
	if _, err := io.ReadFull(r, d.buf); err != nil {
		return err
	}
	d.value(v)
	return nil
}

func Size(v interface{}) int {
	return dataSize(reflect.Indirect(reflect.ValueOf(v)))
}

var structSize sync.Map

func dataSize(v reflect.Value) int {
	switch v.Kind() {
	case reflect.Slice:
		if s := sizeof(v.Type().Elem()); s >= 0 {
			return s * v.Len()
		}
		return -1

	case reflect.Struct:
		t := v.Type()
		if size, ok := structSize.Load(t); ok {
			return size.(int)
		}
		size := sizeof(t)
		structSize.Store(t, size)
		return size

	default:
		return sizeof(v.Type())
	}
}

func sizeof(t reflect.Type) int {
	switch t.Kind() {
	case reflect.Array:
		if s := sizeof(t.Elem()); s >= 0 {
			return s * t.Len()
		}

	case reflect.Struct:
		sum := 0
		for i, n := 0, t.NumField(); i < n; i++ {
			s := sizeof(t.Field(i).Type)
			if s < 0 {
				return -1
			}
			sum += s
		}
		return sum

	case reflect.Bool,
		reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
		reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
		reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
		return int(t.Size())
	}

	return -1
}

type coder struct {
	order  ByteOrder
	buf    []byte
	offset int
}

type decoder coder

func (d *decoder) bool() bool {
	x := d.buf[d.offset]
	d.offset++
	return x != 0
}

func (d *decoder) uint8() uint8 {
	x := d.buf[d.offset]
	d.offset++
	return x
}

func (d *decoder) uint16() uint16 {
	x := d.order.Uint16(d.buf[d.offset : d.offset+2])
	d.offset += 2
	return x
}

func (d *decoder) uint32() uint32 {
	x := d.order.Uint32(d.buf[d.offset : d.offset+4])
	d.offset += 4
	return x
}

func (d *decoder) uint64() uint64 {
	x := d.order.Uint64(d.buf[d.offset : d.offset+8])
	d.offset += 8
	return x
}

func (d *decoder) int8() int8 { return int8(d.uint8()) }
func (d *decoder) int16() int16 { return int16(d.uint16()) }
func (d *decoder) int32() int32 { return int32(d.uint32()) }
func (d *decoder) int64() int64 { return int64(d.uint64()) }

func (d *decoder) value(v reflect.Value) {
	switch v.Kind() {
	case reflect.Array:
		l := v.Len()
		for i := 0; i < l; i++ {
			d.value(v.Index(i))
		}

	case reflect.Struct:
		t := v.Type()
		l := v.NumField()
		for i := 0; i < l; i++ {
			if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
				d.value(v)
			} else {
				d.skip(v)
			}
		}

	case reflect.Slice:
		l := v.Len()
		for i := 0; i < l; i++ {
			d.value(v.Index(i))
		}

	case reflect.Bool:
		v.SetBool(d.bool())

	case reflect.Int8:
		v.SetInt(int64(d.int8()))
	case reflect.Int16:
		v.SetInt(int64(d.int16()))
	case reflect.Int32:
		v.SetInt(int64(d.int32()))
	case reflect.Int64:
		v.SetInt(d.int64())

	case reflect.Uint8:
		v.SetUint(uint64(d.uint8()))
	case reflect.Uint16:
		v.SetUint(uint64(d.uint16()))
	case reflect.Uint32:
		v.SetUint(uint64(d.uint32()))
	case reflect.Uint64:
		v.SetUint(d.uint64())

	case reflect.Float32:
		v.SetFloat(float64(math.Float32frombits(d.uint32())))
	case reflect.Float64:
		v.SetFloat(math.Float64frombits(d.uint64()))

	case reflect.Complex64:
		v.SetComplex(complex(
			float64(math.Float32frombits(d.uint32())),
			float64(math.Float32frombits(d.uint32())),
		))
	case reflect.Complex128:
		v.SetComplex(complex(
			math.Float64frombits(d.uint64()),
			math.Float64frombits(d.uint64()),
		))
	}
}

func (d *decoder) skip(v reflect.Value) {
	d.offset += dataSize(v)
}

func intDataSize(data interface{}) int {
	switch data := data.(type) {
	case bool, int8, uint8, *bool, *int8, *uint8:
		return 1
	case []bool:
		return len(data)
	case []int8:
		return len(data)
	case []uint8:
		return len(data)
	case int16, uint16, *int16, *uint16:
		return 2
	case []int16:
		return 2 * len(data)
	case []uint16:
		return 2 * len(data)
	case int32, uint32, *int32, *uint32:
		return 4
	case []int32:
		return 4 * len(data)
	case []uint32:
		return 4 * len(data)
	case int64, uint64, *int64, *uint64:
		return 8
	case []int64:
		return 8 * len(data)
	case []uint64:
		return 8 * len(data)
	case float32, *float32:
		return 4
	case float64, *float64:
		return 8
	case []float32:
		return 4 * len(data)
	case []float64:
		return 8 * len(data)
	}
	return 0
}

func main() {
    r := strings.NewReader("\x01\x00\x00\x00\x00\x00\x00\x00")
    var data int32
    order := LittleEndian

    err := Read(r, order, &data)
    if err != nil {
        fmt.Println("Error:", err)
    } else {
        fmt.Println(data)
    }
}

Use Case

Binary read

Proposed Solution

No response

Other Information

No response

Acknowledgements

  • I may be able to implement this feature request
  • This feature might incur a breaking change

Version used

latest

Environment details (OS name and version, etc.)

convert to v plz

Note

You can vote for this issue using the 👍 reaction. More votes increase the issue's priority for developers.

Take into account that only the 👍 reaction counts as a vote.
Only reactions to the issue itself will be counted as votes, not comments.

@emma-eva emma-eva added the Feature Request This issue is made to request a feature. label Oct 9, 2023
@ArtemkaKun
Copy link
Contributor

Have you tried https://modules.vlang.io/os.html#read_bytes ?

@ArtemkaKun ArtemkaKun added the Status: Needs More Info The issue author is expected to provide more information. label Oct 11, 2023
@emma-eva
Copy link
Author

Have you tried https://modules.vlang.io/os.html#read_bytes ?

read_bytes work like go binary? does have little endian support?

@ArtemkaKun
Copy link
Contributor

Idk, never worked with binary stuff before. You can also check https://modules.vlang.io/encoding.binary.html, maybe this is what you are looking for

@HimanshuMahto
Copy link

Hey, @ArtemkaKun @emma-eva could you please assign me this issue to work on? It would be great to start from here a new contributor.

@HimanshuMahto
Copy link

Hey, @JalonSolov could you please tell me the location of the code? Please

@JalonSolov
Copy link
Contributor

Which code do you mean?

@HimanshuMahto
Copy link

HimanshuMahto commented Oct 24, 2023

the above one. Which i need to convert into vlang. @JalonSolov

@JalonSolov
Copy link
Contributor

As far as I'm aware, that is the source of the code. Just copy it and paste it into a file.

@HimanshuMahto
Copy link

HimanshuMahto commented Oct 24, 2023

ok, so could you give me any suggestion on what the file's name should be and what should be its location? @JalonSolov

@HimanshuMahto
Copy link

@JalonSolov, done with almost 50% of the code conversion. Could you tell me the name of the file I need to keep and the location of this file?

@JalonSolov
Copy link
Contributor

I think that would be up to @emma-eva as the source of the code.

@HimanshuMahto
Copy link

Hey, @JalonSolov I won't be able to do this. sorry!

@HimanshuMahto HimanshuMahto removed their assignment Oct 24, 2023
@JalonSolov JalonSolov removed Feature Request This issue is made to request a feature. Status: Needs More Info The issue author is expected to provide more information. labels Oct 25, 2023
@JalonSolov
Copy link
Contributor

As I see it, this isn't a V issue at all. It's a request to convert some Go code to V. The purpose of the conversion is unknown, other than perhaps a way to prove it can be done.

@emma-eva
Copy link
Author

emma-eva commented Nov 4, 2023

@JalonSolov, done with almost 50% of the code conversion. Could you tell me the name of the file I need to keep and the location of this file?

Here is full binary code url: https://github.com/golang/go/tree/master/src/encoding/binary

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants