0

I'm trying to create this structure in Golang -

typedef struct FILE_ID_DESCRIPTOR {
  DWORD        dwSize;
  FILE_ID_TYPE Type;
  union {
    LARGE_INTEGER FileId;
    GUID          ObjectId;
    FILE_ID_128   ExtendedFileId;
  } DUMMYUNIONNAME;
} FILE_ID_DESCRIPTOR, *LPFILE_ID_DESCRIPTOR;

As you can see, this depends on union of three in which unknown is FILE_ID_128 and another structure called FILE_ID_TYPE so I stumbled upon this, which is FILE_ID_128s and the _FILE_ID_TYPE structure is here and here

typedef enum _FILE_ID_TYPE {
  FileIdType,
  ObjectIdType,
  ExtendedFileIdType,
  MaximumFileIdType
} FILE_ID_TYPE, *PFILE_ID_TYPE;

And doing after doing some research, I found out that enum is const in Go but in Go, we can not have a named const so maybe a struct(?) and union are byte slices. But I could not find what MaximumFileIdType meant and how to implement that in Go. Thanks in advance.

Also, reference that I am following.

E_net4
  • 27,810
  • 13
  • 101
  • 139
Sushant
  • 3,499
  • 3
  • 17
  • 34
  • What do you mean "we cannot have a named const"? – Jonathan Hall Dec 13 '18 at 09:29
  • What is mean is enums are named in the link that I've provided and used in a different structures but in Go, consts are plain `const (somevar = 1)` – Sushant Dec 13 '18 at 09:30
  • In your example, the name of your const is `somevar`. – Jonathan Hall Dec 13 '18 at 09:53
  • No, what I mean is, for example in C, we define `typedef enum _FILE_ID_TYPE` and use `_FILE_ID_TYPE` in struct `FILE_ID_DESCRIPTOR ` but in Golang, we just say `const (somevar = 1)`, so how do I implement `_FILE_ID_TYPE `? I have posted another link in the answer regarding `FILE_ID_DESCRIPTOR ` – Sushant Dec 13 '18 at 09:59
  • So you mean that Go doesn't support enums, not that it doesn't support named constants? – Jonathan Hall Dec 13 '18 at 10:01
  • Yes, go does not support enums. But I found out enums in C are but consts in Go. Then how do I implement `enum _FILE_ID_TYPE` in Go? – Sushant Dec 13 '18 at 10:02
  • I'm sorry I did not get that @AlexF – Sushant Dec 13 '18 at 10:10
  • 1
    @ThatBird, [`enum`s in C use `int` as their underlying type](https://en.cppreference.com/w/c/language/enum), and have no magic in them: an enum value may be used whereever a plain constant or a value (both of type `int` may be used). Enums have integer values—assigned either automatically (0, 1, …) or manually, and so to emulate a C's enum in Go, you should to two steps: 1) figure out what is the size of `int` in C on your target platform; 2) use one of `intXY` types on your Go side so that its size matches that found on step (1). – kostix Dec 13 '18 at 10:48
  • I always found enums to be a painful and bizarre practice in programming and I am baffled by the many questions from programmers coming from other languages to Go trying to reintroduce them – Vorsprung Dec 13 '18 at 11:25
  • @ThatBird, as to "idiomatic enums", yes, there exist typed constants; you can do something like `const ( foo = int(0); bar = int(1); )` and so on. – kostix Dec 13 '18 at 11:26

1 Answers1

0

Here is ready to use code (taken from here, with fix applyed: in repo the worng size of struct is set, which results in invalid prameter (87) error):

/*Must put file id into ID as big endian; 
little endian form will be placed in descriptor 
automatically when calling id.Descriptor()*/
type ID [16]byte 

func (id ID) Descriptor() Descriptor {
    var structType uint32
    if id.IsInt64() {
        structType = FileType
    } else {
        structType = ExtendedFileIDType
    }

    return Descriptor{
        Size: 24, // (1)
        Type: structType,
        Data: id.LittleEndian(),
    }
}

func (id ID) IsInt64() bool {
    upper := int64(id[0])<<56 | int64(id[1])<<48 | int64(id[2])<<40 | int64(id[3])<<32 | int64(id[4])<<24 | int64(id[5])<<16 | int64(id[6])<<8 | int64(id[7])
    return upper == 0
}

func (id ID) LittleEndian() (value [16]byte) {
    for i := 0; i < 16; i++ {
        value[i] = id[15-i]
    }
    return
}

type Descriptor struct {
    Size uint32
    Type uint32
    Data [16]byte
}

const (
    FileType = iota
    ObjectIDType
    ExtendedFileIDType
)

Some explanation:

(1) size always must be 24 since it must be equal to sizeof(FILE_ID_DESCRIPTOR), which is calculated as follows:

sizeof(DWORD) + sizeof(enum) + sizeof(union)

since DWORD is uint32 the sizeof(DWORD) is 4 bytes; in C++ enums are represented as uint32 too; and sizeof(union) equals the size of largest member of union, which is FILE_ID_128 in our case. size of 128 bit value is 16 bytes. Therefore the above expression can be substituted with:

4 + 4 + 16 = 24

krenix
  • 1
  • 3