// Licensed to Elasticsearch B.V. under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Elasticsearch B.V. licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package dtfmt import ( "errors" "fmt" "unicode/utf8" ) type element interface { requires(c *ctxConfig) error estimateSize() int compile() (prog, error) } type runeLiteral struct { r rune } type stringLiteral struct { s []byte } type unpaddedNumber struct { ft fieldType maxDigits int signed bool } type paddedNumber struct { ft fieldType div int minDigits, maxDigits int signed bool } type textField struct { ft fieldType short bool } type twoDigitYear struct { ft fieldType } type paddingZeros struct { count int } func (runeLiteral) requires(*ctxConfig) error { return nil } func (runeLiteral) estimateSize() int { return 1 } func (stringLiteral) requires(*ctxConfig) error { return nil } func (s stringLiteral) estimateSize() int { return len(s.s) } func (n unpaddedNumber) requires(c *ctxConfig) error { return numRequires(c, n.ft) } func (n unpaddedNumber) estimateSize() int { return numSize(n.maxDigits, n.signed) } func (n paddedNumber) requires(c *ctxConfig) error { return numRequires(c, n.ft) } func (n paddedNumber) estimateSize() int { return numSize(n.maxDigits, n.signed) } func (n twoDigitYear) requires(c *ctxConfig) error { return numRequires(c, n.ft) } func (twoDigitYear) estimateSize() int { return 2 } func numSize(digits int, signed bool) int { if signed { return digits + 1 } return digits } func numRequires(c *ctxConfig, ft fieldType) error { switch ft { case ftYear, ftMonthOfYear, ftDayOfMonth: c.enableDate() case ftWeekyear, ftWeekOfWeekyear: c.enableISO() case ftDayOfYear: c.enableYearday() case ftDayOfWeek: c.enableWeekday() case ftHalfdayOfDay, ftHourOfHalfday, ftClockhourOfHalfday, ftClockhourOfDay, ftHourOfDay, ftMinuteOfDay, ftMinuteOfHour, ftSecondOfDay, ftSecondOfMinute: c.enableClock() case ftMillisOfDay: c.enableClock() c.enableMillis() case ftMillisOfSecond: c.enableMillis() } return nil } func (f textField) requires(c *ctxConfig) error { switch f.ft { case ftHalfdayOfDay: c.enableClock() case ftMonthOfYear: c.enableDate() case ftDayOfWeek: c.enableWeekday() default: return fmt.Errorf("time field %v not supported by text", f.ft) } return nil } func (f textField) estimateSize() int { switch f.ft { case ftHalfdayOfDay: return 2 case ftDayOfWeek: if f.short { return 3 } return 9 // max(weekday) = len(Wednesday) case ftMonthOfYear: if f.short { return 6 } return 9 // max(month) = len(September) default: return 0 } } func (r runeLiteral) compile() (prog, error) { switch utf8.RuneLen(r.r) { case -1: return prog{}, errors.New("invalid rune") } var tmp [8]byte l := utf8.EncodeRune(tmp[:], r.r) return makeCopy(tmp[:l]) } func (s stringLiteral) compile() (prog, error) { return makeCopy([]byte(s.s)) } func (n unpaddedNumber) compile() (prog, error) { return makeProg(opNum, byte(n.ft)) } func (n paddedNumber) compile() (prog, error) { if n.div == 0 { return makeProg(opNumPadded, byte(n.ft), byte(n.maxDigits)) } return makeProg(opExtNumPadded, byte(n.ft), byte(n.div), byte(n.maxDigits)) } func (n twoDigitYear) compile() (prog, error) { return makeProg(opTwoDigit, byte(n.ft)) } func (f textField) compile() (prog, error) { if f.short { return makeProg(opTextShort, byte(f.ft)) } return makeProg(opTextLong, byte(f.ft)) } func (p paddingZeros) requires(c *ctxConfig) error { return nil } func (p paddingZeros) estimateSize() int { return p.count } func (p paddingZeros) compile() (prog, error) { return makeProg(opZeros, byte(p.count)) }