class Vobject::Vcalendar::Typegrammars

Public Class Methods

actionvalue() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 341
def actionvalue
  actionvalue = (/AUDIO/i.r | /DISPLAY/i.r | /EMAIL/i.r | C::IANATOKEN |
                 C::XNAME_VCAL).map { |m| PropertyValue::ActionValue.new m }
  actionvalue.eof
end
binary() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 186
def binary
  binary = seq(/[a-zA-Z0-9+\/]*/.r, /={0,2}/.r) do |(b, q)|
    if (b.length + q.length) % 4 == 0
      PropertyValue::Binary.new(b + q)
    else
      { error: "Malformed binary coding" }
    end
  end
  binary.eof
end
boolean() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 347
def boolean
  boolean = C::BOOLEAN.map { |b| PropertyValue::Boolean.new b }
  boolean.eof
end
busytype() click to toggle source

RFC 7953

# File lib/vobject/vcalendar/typegrammars.rb, line 361
def busytype
  busytype = (/BUSY-UNAVAILABLE/i.r | /BUSY-TENTATIVE/i.r | /BUSY/i.r |
              C::IANATOKEN |
              C::XNAME_VCAL).map { |m| PropertyValue::BusyType.new m }
  busytype.eof
end
calscalevalue() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 164
def calscalevalue
  calscalevalue = /GREGORIAN/i.r.map { PropertyValue::Calscale.new "GREGORIAN" }
  calscalevalue.eof
end
classvalue() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 233
def classvalue
  classvalue = (/PUBLIC/i.r | /PRIVATE/i.r | /CONFIDENTIAL/i.r | C::XNAME_VCAL | C::IANATOKEN).map do |m|
    PropertyValue::ClassValue.new m
  end
  classvalue.eof
end
color() click to toggle source

www.w3.org/TR/2011/REC-css3-color-20110607/#svg-color

# File lib/vobject/vcalendar/typegrammars.rb, line 369
def color
  color = C::COLOR.map { |m| PropertyValue::Color.new m }
  color.eof
end
date_t() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 261
def date_t
  date_t = C::DATE
  date_t.eof
end
date_time_t() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 274
def date_time_t
  C::DATE_TIME.eof
end
date_time_utc_t() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 289
def date_time_utc_t
  date_time_utc_t = C::DATE_TIME_UTC
  date_time_utc_t.eof
end
date_time_utclist() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 294
def date_time_utclist
  date_time_utclist1 = seq(C::DATE_TIME_UTC << ",".r, lazy { date_time_utclist1 }) do |(d, l)|
    [d, l].flatten
  end | C::DATE_TIME_UTC.map { |d| [d] }
  date_time_utclist = date_time_utclist1.map do |m|
    PropertyValue::Datetimeutclist.new m
  end
  date_time_utclist.eof
end
date_timelist() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 278
def date_timelist
  date_timelist1 = seq(C::DATE_TIME << ",".r,
                       lazy { date_timelist1 }) do |(d, l)|
    [d, l].flatten
  end | C::DATE_TIME.map { |d| [d] }
  date_timelist = date_timelist1.map do |m|
    PropertyValue::Datetimelist.new m
  end
  date_timelist.eof
end
datelist() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 266
def datelist
  datelist1 = seq(C::DATE << ",".r, lazy { datelist1 }) do |(d, l)|
    [d, l].flatten
  end | C::DATE.map { |d| [d] }
  datelist = datelist1.map { |m| PropertyValue::Datelist.new m }
  datelist.eof
end
duration_t() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 304
def duration_t
  duration = C::DURATION.map { |d| PropertyValue::Duration.new d }
  duration.eof
end
eventstatus() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 240
def eventstatus
  eventstatus = (/TENTATIVE/i.r | /CONFIRMED/i.r | /CANCELLED/i.r).map do |m|
    PropertyValue::EventStatus.new m
  end
  eventstatus.eof
end
float_t() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 142
def float_t
  float_t = prim(:double).map { |f| PropertyValue::Float.new f }
  float_t.eof
end
geovalue() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 152
def geovalue
  float = prim(:double)
  geovalue = seq(float << ";".r, float) do |(a, b)|
    if a <= 180.0 && a >= -180.0 && b <= 180 && b > -180
      PropertyValue::Geovalue.new(lat: a, long: b)
    else
      { error: "Latitude/Longitude outside of range -180..180" }
    end
  end
  geovalue.eof
end
iana_token() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 169
def iana_token
  iana_token = C::IANATOKEN.map { |x| PropertyValue::Ianatoken.new x }
  iana_token.eof
end
integer() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 115
def integer
  integer = prim(:int32).map { |i| PropertyValue::Integer.new i }
  integer.eof
end
journalstatus() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 254
def journalstatus
  journalstatus = (/DRAFT/i.r | /FINAL/i.r | /CANCELLED/i.r).map do |m|
    PropertyValue::Journalstatus.new m
  end
  journalstatus.eof
end
methodvalue() click to toggle source

RFC 5546

# File lib/vobject/vcalendar/typegrammars.rb, line 353
def methodvalue
  methodvalue = (/PUBLISH/i.r | /REQUEST/i.r | /REPLY/i.r | /ADD/i.r |
                 /CANCEL/i.r | /REFRESH/i.r | /COUNTER/i.r |
                 /DECLINECOUNTER/i.r).map { |m| PropertyValue::MethodValue.new m }
  methodvalue.eof
end
percent_complete() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 120
def percent_complete
  integer = prim(:int32).map do |a|
    if a >= 0 && a <= 100
      PropertyValue::PercentComplete.new a
    else
      { error: "Percentage outside of range 0..100" }
    end
  end
  integer.eof
end
periodlist() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 309
def periodlist
  period_explicit = seq(C::DATE_TIME << "/".r, C::DATE_TIME) do |(s, e)|
    { start: s, end: e }
  end
  period_start = seq(C::DATE_TIME << "/".r, C::DURATION) do |(s, d)|
    { start: s, duration: PropertyValue::Duration.new(d) }
  end
  period = period_explicit | period_start
  periodlist1 = seq(period << ",".r, lazy { periodlist1 }) do |(p, l)|
    [p, l].flatten
  end | period.map { |p| [p] }
  periodlist = periodlist1.map { |m| PropertyValue::Periodlist.new m }
  periodlist.eof
end
priority() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 131
def priority
  integer = prim(:int32).map do |a|
    if a >= 0 && a <= 9
      PropertyValue::Priority.new a
    else
      { error: "Percentage outside of range 0..100" }
    end
  end
  integer.eof
end
property_parent(strict, key, component, _value, ctx1) click to toggle source

Ensure each property belongs to a legal component

# File lib/vobject/vcalendar/propertyparent.rb, line 15
def property_parent(strict, key, component, _value, ctx1)
  errors = []
  if key !~ /^x/i && registered_propname?(key.to_s)
    case component
    when :EVENT
      case key
      when :DTSTAMP, :UID, :DTSTART, :CLASS, :CREATED, :DESCRIPTION,
        :GEO, :LAST_MOD, :LOCATION, :ORGANIZER, :PRIORITY, :SEQUENCE, :STATUS,
        :SUMMARY, :TRANSP, :URL, :RECURRENCE_ID, :RRULE, :DTEND, :DURATION,
        :ATTACH, :ATTENDEE, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE,
        :RSTATUS, :RELATED, :RESOURCES, :RDATE, :COLOR, :CONFERENCE, :IMAGE
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :TODO
      case key
      when :DTSTAMP, :UID, :DTSTART, :CLASS, :CREATED, :DESCRIPTION,
        :GEO, :LAST_MOD, :LOCATION, :ORGANIZER, :PRIORITY, :PERCENT_COMPLETED, :SEQUENCE, :STATUS,
        :SUMMARY, :URL, :RECURRENCE_ID, :RRULE, :DUE, :DURATION,
        :ATTACH, :ATTENDEE, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE,
        :RSTATUS, :RELATED, :RESOURCES, :RDATE, :COLOR, :CONFERENCE, :IMAGE
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :JOURNAL
      case key
      when :DTSTAMP, :UID, :DTSTART, :CLASS, :CREATED, :DESCRIPTION,
        :LAST_MOD, :ORGANIZER, :RECURRENCE_ID, :SEQUENCE, :STATUS,
        :SUMMARY, :URL, :RRULE,
        :ATTACH, :ATTENDEE, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE,
        :RSTATUS, :RELATED, :RDATE, :COLOR, :IMAGE
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :FREEBUSY
      case key
      when :DTSTAMP, :UID, :CONTACT, :DTSTART, :DTEND, :ORGANIZER, :URL,
        :ATTENDEE, :COMMENT, :FREEBUSY, :RSTATUS
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :TIMEZONE
      case key
      when :TZID, :LAST_MODIFIED, :TZURL
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :DAYLIGHT, :STANDARD
      case key
      when :DTSTART, :TZOFFSETTO, :TZOFFSETFROM, :RRULE,
        :COMMENT, :RDATE, :TZNAME
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :ALARM
      case key
      when :ACTION, :TRIGGER, :DURATION, :REPEAT, :ATTACH, :DESCRIPTION,
        :SUMMARY, :ATTENDEE
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :VAVAILABILITY
      case key
      when :DTSTAMP, :UID, :BUSYTYPE, :CLASS, :CREATED, :DESCRIPTION,
        :DTSTART, :LAST_MODIFIED, :LOCATION, :ORGANIZER, :PRIORITY, :SEQUENCE,
        :SUMMARY, :URL, :DTEND, :DURATION, :CATEGORIES, :COMMENT, :CONTACT
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    when :AVAILABLE
      case key
      when :DTSTAMP, :DTSTART, :UID, :DTEND, :DURATION, :CREATED,
        :DESCRIPTION, :LAST_MODIFIED, :LOCATION, :RECURRENCE_ID, :RRULE,
        :SUMMARY, :CATEGORIES, :COMMENT, :CONTACT, :EXDATE, :RDATE
      else
        parse_err(strict, errors, "Invalid property #{key} specified for #{component}", ctx1)
      end
    end
  end
  errors
end
recur() click to toggle source

property value types, each defining their own parser

# File lib/vobject/vcalendar/typegrammars.rb, line 17
def recur
  freq = /SECONDLY/i.r | /MINUTELY/i.r | /HOURLY/i.r | /DAILY/i.r |
    /WEEKLY/i.r | /MONTHLY/i.r | /YEARLY/i.r
  enddate = C::DATE_TIME | C::DATE
  seconds = /[0-9]{1,2}/.r
  byseclist = seq(seconds << ",".r, lazy { byseclist }) do |(s, l)|
    [s, l].flatten
  end | seconds.map { |s| [s] }
  minutes = /[0-9]{1,2}/.r
  byminlist = seq(minutes << ",".r, lazy { byminlist }) do |(m, l)|
    [m, l].flatten
  end | minutes.map { |m| [m] }
  hours = /[0-9]{1,2}/.r
  byhrlist = seq(hours << ",".r, lazy { byhrlist }) do |(h, l)|
    [h, l].flatten
  end | hours.map { |h| [h] }
  ordwk = /[0-9]{1,2}/.r
  weekday = /SU/i.r | /MO/i.r | /TU/i.r | /WE/i.r | /TH/i.r | /FR/i.r | /SA/i.r
  weekdaynum1 = seq(C::SIGN._?, ordwk) do |(s, o)|
    h = { ordwk: o }
    h[:sign] = s[0] unless s.empty?
    h
  end
  weekdaynum = seq(weekdaynum1._?, weekday) do |(a, b)|
    h = { weekday: b }
    h = h.merge a[0] unless a.empty?
    h
  end
  bywdaylist = seq(weekdaynum << ",".r, lazy { bywdaylist }) do |(w, l)|
    [w, l].flatten
  end | weekdaynum.map { |w| [w] }
  ordmoday = /[0-9]{1,2}/.r
  monthdaynum = seq(C::SIGN._?, ordmoday) do |(s, o)|
    h = { ordmoday: o }
    h[:sign] = s[0] unless s.empty?
    h
  end
  bymodaylist = seq(monthdaynum << ",".r, lazy { bymodaylist }) do |(m, l)|
    [m, l].flatten
  end | monthdaynum.map { |m| [m] }
  ordyrday = /[0-9]{1,3}/.r
  yeardaynum = seq(C::SIGN._?, ordyrday) do |(s, o)|
    h = { ordyrday: o }
    h[:sign] = s[0] unless s.empty?
    h
  end
  byyrdaylist = seq(yeardaynum << ",".r, lazy { byyrdaylist }) do |(y, l)|
    [y, l].flatten
  end | yeardaynum.map { |y| [y] }
  weeknum = seq(C::SIGN._?, ordwk) do |(s, o)|
    h = { ordwk: o }
    h[:sign] = s[0] unless s.empty?
    h
  end
  bywknolist = seq(weeknum << ",".r, lazy { bywknolist }) do |(w, l)|
    [w, l].flatten
  end | weeknum.map { |w| [w] }
  # monthnum = /[0-9]{1,2}/.r
  # RFC 7529 add leap month indicator
  monthnum = /[0-9]{1,2}L?/i.r
  bymolist = seq(monthnum << ",".r, lazy { bymolist }) do |(m, l)|
    [m, l].flatten
  end | monthnum.map { |m| [m] }
  setposday = yeardaynum
  bysplist = seq(setposday << ",".r, lazy { bysplist }) do |(s, l)|
    [s, l].flatten
  end | setposday.map { |s| [s] }
  # http://www.unicode.org/repos/cldr/tags/latest/common/bcp47/calendar.xml
  rscale = C::XNAME_VCAL | /buddhist/i.r | /chinese/i.r | /coptic/i.r | /dangi/i.r |
    /ethioaa/i.r | /ethiopic-amete-alem/i.r | /ethiopic/i.r |
    /gregory/i.r | /hebrew/i.r | /indian/i.r | /islamic/i.r |
    /islamic-umalqura/i.r | /islamic-tbla/i.r | /islamic-civil/i.r |
    /islamic-rgsa/i.r | /iso8601/i.r | /japanese/i.r | /persian/i.r |
    /roc/i.r | /islamicc/i.r | /gregorian/i.r
  skip = /OMIT/i.r | /BACKWARD/i.r | /FORWARD/i.r
  recur_rule_part =       seq(/FREQ/i.r << "=".r, freq) { |(_k, v)| { freq: v } } |
    seq(/UNTIL/i.r << "=".r, enddate) { |(_k, v)| { until: v } } |
    seq(/COUNT/i.r << "=".r, /[0-9]+/i.r) { |(_k, v)| { count: v } } |
    seq(/INTERVAL/i.r << "=".r, /[0-9]+/i.r) { |(_k, v)| { interval: v } } |
    seq(/BYSECOND/i.r << "=".r, byseclist) { |(_k, v)| { bysecond: v } } |
    seq(/BYMINUTE/i.r << "=".r, byminlist) { |(_k, v)| { byminute: v } } |
    seq(/BYHOUR/i.r << "=".r, byhrlist) { |(_k, v)| { byhour: v } } |
    seq(/BYDAY/i.r << "=".r, bywdaylist) { |(_k, v)| { byday: v } } |
    seq(/BYMONTHDAY/i.r << "=".r, bymodaylist) { |(_k, v)| { bymonthday: v } } |
    seq(/BYYEARDAY/i.r << "=".r, byyrdaylist) { |(_k, v)| { byyearday: v } } |
    seq(/BYWEEKNO/i.r << "=".r, bywknolist) { |(_k, v)| { byweekno: v } } |
    seq(/BYMONTH/i.r << "=".r, bymolist) { |(_k, v)| { bymonth: v } } |
    seq(/BYSETPOS/i.r << "=".r, bysplist) { |(_k, v)| { bysetpos: v } } |
    seq(/WKST/i.r << "=".r, weekday) { |(_k, v)| { wkst: v } } |
    # RFC 7529
    seq(/RSCALE/i.r << "=".r, rscale) { |(_k, v)| { rscale: v } } |
    seq(/SKIP/i.r << "=".r, skip) { |(_k, v)| { skip: v } }
  recur1 = seq(recur_rule_part, ";", lazy { recur1 }) { |(h, _, r)| h.merge r } |
    recur_rule_part
  recur = recur1.map { |r| PropertyValue::Recur.new r }
  recur.eof
end
registered_propname() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 381
def registered_propname
  registered_propname = C::NAME_VCAL
  registered_propname.eof
end
registered_propname?(x) click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 386
def registered_propname?(x)
  p = registered_propname.parse(x)
  not(Rsec::INVALID[p])
end
request_statusvalue() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 221
def request_statusvalue
  @req_status = Set.new %w{2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.10 2.11 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 4.0 5.0 5.1 5.2 5.3}
  extdata = seq(";".r, C::TEXT) { |(_, t)| t }
  request_statusvalue = seq(/[0-9](\.[0-9]){1,2}/.r << ";".r, C::TEXT, extdata._?) do |(n, t1, t2)|
    return { error: "Invalid request status #{n}" } unless @req_status.include?(n) # RFC 5546
    hash = { statcode: n, statdesc: t1 }
    hash[:extdata] = t2[0] unless t2.empty?
    Vobject::Vcalendar::PropertyValue::Requeststatusvalue.new hash
  end
  request_statusvalue.eof
end
text_t() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 208
def text_t
  text_t = C::TEXT.map { |t| PropertyValue::Text.new(unescape(t)) }
  text_t.eof
end
textlist() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 213
def textlist
  textlist1 =
    seq(C::TEXT << ",".r, lazy { textlist1 }) { |(a, b)| [unescape(a), b].flatten } |
    C::TEXT.map { |t| [unescape(t)] }
  textlist = textlist1.map { |m| PropertyValue::Textlist.new m }
  textlist.eof
end
time_t() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 147
def time_t
  time_t = C::TIME.map { |t| PropertyValue::Time.new t }
  time_t.eof
end
todostatus() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 247
def todostatus
  todostatus = (/NEEDS-ACTION/i.r | /COMPLETED/i.r | /IN-PROCESS/i.r | /CANCELLED/i.r).map do |m|
    PropertyValue::Todostatus.new m
  end
  todostatus.eof
end
transpvalue() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 324
def transpvalue
  transpvalue = (/OPAQUE/i.r | /TRANSPARENT/i.r).map do |m|
    PropertyValue::TranspValue.new m
  end
  transpvalue.eof
end
typematch(strict, key, params, component, value, ctx) click to toggle source

Enforce type restrictions on values of particular properties. If successful, return typed interpretation of string

# File lib/vobject/vcalendar/typegrammars.rb, line 393
def typematch(strict, key, params, component, value, ctx)
  errors = []
  errors << property_parent(strict, key, component, value, ctx)
  ctx1 = Rsec::ParseContext.new value, "source"
  case key
  when :CALSCALE
    ret = calscalevalue._parse ctx1
  when :METHOD
    ret = methodvalue._parse ctx1
  when :VERSION
    ret = versionvalue._parse ctx1
  when :ATTACH
    ret = if params[:VALUE] == "BINARY"
            binary._parse ctx1
          else
            uri._parse ctx1
          end
  when :IMAGE
    parse_err(strict, errors, "No VALUE parameter specified for property #{key}", ctx1) if params.empty?
    parse_err(strict, errors, "No VALUE parameter specified for property #{key}", ctx1) unless params[:VALUE]
    if params[:VALUE] == "BINARY"
      parse_err(strict, errors, "No ENCODING parameter specified for property #{key}", ctx1) unless params[:ENCODING]
      parse_err(strict, errors, "Incorrect ENCODING parameter specified for property #{key}", ctx1) unless params[:ENCODING] == "BASE64"
      ret = binary._parse ctx1
    elsif params[:VALUE] == "URI"
      ret = uri._parse ctx1
    else
      parse_err(strict, errors, "Incorrect VALUE parameter specified for property #{key}", ctx1)
    end
  when :CATEGORIES, :RESOURCES
    ret = textlist._parse ctx1
  when :CLASS
    ret = classvalue._parse ctx1
  when :COMMENT, :DESCRIPTION, :LOCATION, :SUMMARY, :TZID, :TZNAME,
    :CONTACT, :RELATED_TO, :UID, :PRODID, :NAME
    ret = text_t._parse ctx1
  when :GEO
    ret = geovalue._parse ctx1
  when :PERCENT_COMPLETE
    ret = percent_complete._parse ctx1
  when :PRIORITY
    ret = priority._parse ctx1
  when :STATUS
    ret = case component
          when :EVENT
            eventstatus._parse ctx1
          when :TODO
            todostatus._parse ctx1
          when :JOURNAL
            journalstatus._parse ctx1
          else
            text_t._parse ctx1
          end
  when :COMPLETED, :CREATED, :DTSTAMP, :LAST_MODIFIED
    ret = date_time_utc_t._parse ctx1
  when :DTEND, :DTSTART, :DUE, :RECURRENCE_ID
    if params && params[:VALUE] == "DATE"
      ret = date_t._parse ctx1
    elsif component == :FREEBUSY
      ret = date_time_utc_t._parse ctx1
    elsif params && params[:TZID]
      if [:STANDARD || :DAYLIGHT].include? component
        parse_err(strict, errors, "Specified TZID within property #{key} in #{component}", ctx1)
      end
      begin
        tz = TZInfo::Timezone.get(params[:TZID])
        ret = date_time_t._parse ctx1
        # note that we use the registered tz information to map to UTC, rather than look up the values witin the VTIMEZONE component
        ret.value[:time] = tz.local_to_utc(ret.value[:time])
        ret.value[:zone] = params[:TZID]
      rescue
        # undefined timezone: default to floating local
        ret = date_time_t._parse ctx1
      end
    else
      ret = date_time_t._parse ctx1
    end
  when :EXDATE
    if params && params[:VALUE] == "DATE"
      ret = datelist._parse ctx1
    elsif params && params[:TZID]
      if [:STANDARD || :DAYLIGHT].include? component
        parse_err(strict, errors, "Specified TZID within property #{key} in #{component}", ctx1)
      end
      tz = TZInfo::Timezone.get(params[:TZID])
      ret = date_timelist._parse ctx1
      ret.value.each do |x|
        x.value[:time] = tz.local_to_utc(x.value[:time])
        x.value[:zone] = params[:TZID]
      end
    else
      ret = date_timelist._parse ctx1
    end
  when :RDATE
    if params && params[:VALUE] == "DATE"
      ret = datelist._parse ctx1
    elsif params && params[:VALUE] == "PERIOD"
      ret = periodlist._parse ctx1
    elsif params && params[:TZID]
      if [:STANDARD || :DAYLIGHT].include? component
        parse_err(strict, errors, "Specified TZID within property #{key} in #{component}", ctx1)
      end
      tz = TZInfo::Timezone.get(params[:TZID])
      ret = date_timelist._parse ctx1
      ret.value.each do |x|
        x.value[:time] = tz.local_to_utc(x.value[:time])
        x.value[:zone] = params[:TZID]
      end
    else
      ret = date_timelist._parse ctx1
    end
  when :TRIGGER
    if params && params[:VALUE] == "DATE-TIME" || /^\d{8}T/.match(value)
      if params && params[:RELATED]
        parse_err(strict, errors, "Specified RELATED within property #{key} as date-time", ctx1)
      end
      ret = date_time_utc_t._parse ctx1
    else
      ret = duration_t._parse ctx1
    end
  when :FREEBUSY
    ret = periodlist._parse ctx1
  when :TRANSP
    ret = transpvalue._parse ctx1
  when :TZOFFSETFROM, :TZOFFSETTO
    ret = utc_offset._parse ctx1
  when :TZURI, :URL, :SOURCE, :CONFERENCE
    if key == :CONFERENCE
      parse_err(strict, errors, "Missing URI VALUE parameter", ctx1) if params.empty?
      parse_err(strict, errors, "Missing URI VALUE parameter", ctx1) if !params[:VALUE]
      parse_err(strict, errors, "report_error Type mismatch of VALUE parameter #{params[:VALUE]} for property #{key}", ctx1) if params[:VALUE] != "URI"
    end
    ret = uri._parse ctx1
  when :ATTENDEE, :ORGANIZER
    ret = uri._parse ctx1
  when :RRULE
    ret = recur._parse ctx1
  when :ACTION
    ret = actionvalue._parse ctx1
  when :REPEAT, :SEQUENCE
    ret = integer._parse ctx1
  when :REQUEST_STATUS
    ret = request_statusvalue._parse ctx1
    # RFC 7953
  when :BUSYTYPE
    ret = busytype._parse ctx1
    # RFC 7986
  when :REFRESH_INTERVAL
    parse_err(strict, errors, "Missing VALUE parameter for property #{key}", ctx1) if params.empty?
    parse_err(strict, errors, "Missing VALUE parameter for property #{key}", ctx1) if !params[:VALUE]
    parse_err(strict, errors, "Type mismatch of VALUE parameter #{params[:VALUE]} for property #{key}", ctx1) if params[:VALUE] != "DURATION"
    ret = duration_t._parse ctx1
    # RFC 7986
  when :COLOR
    ret = color._parse ctx1
  else
    if params && params[:VALUE]
      case params[:VALUE]
      when "BOOLEAN"
        ret = boolean._parse ctx1
      when "BINARY"
        ret = binary._parse ctx1
      when "CAL-ADDRESS"
        ret = uri._parse ctx1
      when "DATE-TIME"
        ret = date_time_t._parse ctx1
      when "DATE"
        ret = date_t._parse ctx1
      when "DURATION"
        ret = duration_t._parse ctx1
      when "FLOAT"
        ret = float_t._parse ctx1
      when "INTEGER"
        ret = integer._parse ctx1
      when "PERIOD"
        ret = period._parse ctx1
      when "RECUR"
        ret = recur._parse ctx1
      when "TEXT"
        ret = text_t._parse ctx1
      when "TIME"
        ret = time_t._parse ctx1
      when "URI"
        ret = uri._parse ctx1
      when "UTC-OFFSET"
        ret = utc_offset._parse ctx1
      end
    else
      ret = text_t._parse ctx1
    end
  end
  if ret.is_a?(Hash) && ret[:error]
    parse_err(strict, errors, "#{ret[:error]} for property #{key}, value #{value}", ctx)
  end
  if Rsec::INVALID[ret]
    parse_err(strict, errors, "Type mismatch for property #{key}, value #{value}", ctx)
  end
  Rsec::Fail.reset
  [ret, errors]
end
unescape(x) click to toggle source

text escapes: \ ; , N n

# File lib/vobject/vcalendar/typegrammars.rb, line 375
def unescape(x)
  # temporarily escape \\ as \007f, which is disallowed in any text
  x.gsub(/\\\\/, "\u007f").gsub(/\\;/, ";").gsub(/\\,/, ",").
    gsub(/\\[Nn]/, "\n").tr("\u007f", "\\")
end
uri() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 197
def uri
  uri = /\S+/.r.map do |s|
    if s =~ URI::DEFAULT_PARSER.make_regexp
      PropertyValue::Uri.new(s)
    else
      { error: "Invalid URI" }
    end
  end
  uri.eof
end
utc_offset() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 331
def utc_offset
  utc_offset = seq(C::SIGN, /[0-9]{2}/.r, /[0-9]{2}/.r,
                   /[0-9]{2}/.r._?) do |(sign, h, m, sec)|
    hash = { sign: sign, hr: h, min: m }
    hash[:sec] = sec[0] unless sec.empty?
    PropertyValue::Utcoffset.new hash
  end
  utc_offset.eof
end
versionvalue() click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 174
def versionvalue
  versionvalue = seq(prim(:double) << ";".r,
                     prim(:double)) do |(x, y)|
    PropertyValue::Version.new [x, y]
  end | "2.0".r.map do
    PropertyValue::Version.new ["2.0"]
  end | prim(:double).map do |v|
    PropertyValue::Version.new v
  end
  versionvalue.eof
end

Private Class Methods

parse_err(strict, errors, msg, ctx) click to toggle source
# File lib/vobject/vcalendar/typegrammars.rb, line 596
def parse_err(strict, errors, msg, ctx)
  if strict
    raise ctx.report_error msg, "source"
  else
    errors << ctx.report_error(msg, "source")
  end
end