moov-io / iso8583

A golang implementation to marshal and unmarshal iso8583 message.
https://moov.io
Apache License 2.0
304 stars 100 forks source link

New provision to get fields from specs. #174

Open magudelo58 opened 2 years ago

magudelo58 commented 2 years ago

In the describe.go we can get the description from the Specs with the instruction "desc := field.Spec().Description".

There is not provision to get other fields, per example Encoding. I have tried enc := field.Spec().Enc and so far I can just print "&{}"

The goal is to produce an output like this:

DE FMT LEN DESCRIPTION DATA


MTI HEX 0004 Message Type Indicator [1130] 000 HEX 0016 Bitmap, Primary [F676A7458AE0A014] 001 HEX 0016 Bitmap, Secondary [0000000000000020] 002 LL 0016 PAN [5275****3790] ...

Can we add new method to get other fields defined in the specs: encoding, prefix?

alovak commented 2 years ago

I see that in the Prefixer we have Inspect() string method. In the Padder we have Inspect() []byte. It seems like a good idea to unify them all (fix returning type, etc.) and support such inspection.

On the other hand, adding meta information into interfaces seems wrong. We may have different use cases, and modifying the interface to support it is not always practical. The goal of the reflect package is:

The typical use is to take a value with static type interface{} and extract its dynamic type information by calling TypeOf, which returns a Type.

So, an alternative way I see is to remove all Inspect() methods and replace them with reflect in the Describe method and everywhere else. I'm leaning towards the latter as it will keep only core functionality. While the rest can be achieved by other means.

alovak commented 2 years ago

For the issue, you can follow the same approach as we use in specs.Builder here: https://github.com/moov-io/iso8583/blob/1e9be380ac9a583f5faf64516783cbc3f146df69/specs/builder.go#L319

func exportEnc(enc encoding.Encoder) (string, error) {
    // set encoding
    encType := reflect.TypeOf(enc).Elem().Name()
    if e, found := EncodingsIntToExt[encType]; found {
        return e, nil
    } else {
        return "", fmt.Errorf("unknown encoding type: %s", encType)
    }
}
magudelo58 commented 2 years ago

Hi @alovak, I see the method you are describing is already in specs.Builder as you are mentioning.

I guess I'm referring to the exposure of those internal methods at the field level, similar to field.Spec().Description but it would be like field.Spec().Encoding or field.Spec().Prefix

alovak commented 10 months ago

For each package like prefix, padding, encoding we can create Name function that will return the name of respecting thing like:

encName :=  encoding.Name(encoding.ASCII) // return "" if not found
prefixName := prefix.Name(prefix.ASCII.Fixed) // return "" if not found
// ...

we can implement it based on what we have here: https://github.com/moov-io/iso8583/blob/master/specs/builder.go#L162