Skip to content

Commit

Permalink
Replace reflection-based memoization with Lazy.Fody
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyrrrz committed Aug 20, 2023
1 parent 530517f commit 9d31e97
Show file tree
Hide file tree
Showing 15 changed files with 650 additions and 814 deletions.
37 changes: 16 additions & 21 deletions YoutubeExplode/Bridge/ChannelPage.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using AngleSharp.Html.Dom;
using Lazy;
using YoutubeExplode.Utils;
using YoutubeExplode.Utils.Extensions;

Expand All @@ -9,27 +10,21 @@ internal partial class ChannelPage
{
private readonly IHtmlDocument _content;

public string? Url => Memo.Cache(this, () =>
_content
.QuerySelector("meta[property=\"og:url\"]")?
.GetAttribute("content")
);

public string? Id => Memo.Cache(this, () =>
Url?.SubstringAfter("channel/", StringComparison.OrdinalIgnoreCase)
);

public string? Title => Memo.Cache(this, () =>
_content
.QuerySelector("meta[property=\"og:title\"]")?
.GetAttribute("content")
);

public string? LogoUrl => Memo.Cache(this, () =>
_content
.QuerySelector("meta[property=\"og:image\"]")?
.GetAttribute("content")
);
[Lazy]
public string? Url => _content.QuerySelector("meta[property=\"og:url\"]")?.GetAttribute("content");

[Lazy]
public string? Id => Url?.SubstringAfter("channel/", StringComparison.OrdinalIgnoreCase);

[Lazy]
public string? Title => _content
.QuerySelector("meta[property=\"og:title\"]")?
.GetAttribute("content");

[Lazy]
public string? LogoUrl => _content
.QuerySelector("meta[property=\"og:image\"]")?
.GetAttribute("content");

public ChannelPage(IHtmlDocument content) => _content = content;
}
Expand Down
49 changes: 22 additions & 27 deletions YoutubeExplode/Bridge/ClosedCaptionTrackResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Lazy;
using YoutubeExplode.Utils;
using YoutubeExplode.Utils.Extensions;

Expand All @@ -11,12 +12,11 @@ internal partial class ClosedCaptionTrackResponse
{
private readonly XElement _content;

public IReadOnlyList<CaptionData> Captions => Memo.Cache(this, () =>
_content
.Descendants("p")
.Select(x => new CaptionData(x))
.ToArray()
);
[Lazy]
public IReadOnlyList<CaptionData> Captions => _content
.Descendants("p")
.Select(x => new CaptionData(x))
.ToArray();

public ClosedCaptionTrackResponse(XElement content) => _content = content;
}
Expand All @@ -27,24 +27,20 @@ public class CaptionData
{
private readonly XElement _content;

public string? Text => Memo.Cache(this, () =>
(string?)_content
);
[Lazy]
public string? Text => (string?)_content;

public TimeSpan? Offset => Memo.Cache(this, () =>
((double?)_content.Attribute("t"))?.Pipe(TimeSpan.FromMilliseconds)
);
[Lazy]
public TimeSpan? Offset => ((double?)_content.Attribute("t"))?.Pipe(TimeSpan.FromMilliseconds);

public TimeSpan? Duration => Memo.Cache(this, () =>
((double?)_content.Attribute("d"))?.Pipe(TimeSpan.FromMilliseconds)
);
[Lazy]
public TimeSpan? Duration => ((double?)_content.Attribute("d"))?.Pipe(TimeSpan.FromMilliseconds);

public IReadOnlyList<PartData> Parts => Memo.Cache(this, () =>
_content
.Elements("s")
.Select(x => new PartData(x))
.ToArray()
);
[Lazy]
public IReadOnlyList<PartData> Parts => _content
.Elements("s")
.Select(x => new PartData(x))
.ToArray();

public CaptionData(XElement content) => _content = content;
}
Expand All @@ -56,15 +52,14 @@ public class PartData
{
private readonly XElement _content;

public string? Text => Memo.Cache(this, () =>
(string?)_content
);
[Lazy]
public string? Text => (string?)_content;

public TimeSpan? Offset => Memo.Cache(this, () =>
[Lazy]
public TimeSpan? Offset =>
((double?)_content.Attribute("t"))?.Pipe(TimeSpan.FromMilliseconds) ??
((double?)_content.Attribute("ac"))?.Pipe(TimeSpan.FromMilliseconds) ??
TimeSpan.Zero
);
TimeSpan.Zero;

public PartData(XElement content) => _content = content;
}
Expand Down
122 changes: 56 additions & 66 deletions YoutubeExplode/Bridge/DashManifest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Net;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using Lazy;
using YoutubeExplode.Utils;
using YoutubeExplode.Utils.Extensions;

Expand All @@ -12,30 +13,29 @@ internal partial class DashManifest
{
private readonly XElement _content;

public IReadOnlyList<IStreamData> Streams => Memo.Cache(this, () =>
_content
.Descendants("Representation")
// Skip non-media representations (like "rawcc")
// https://github.com/Tyrrrz/YoutubeExplode/issues/546
.Where(x => x
.Attribute("id")?
.Value
.All(char.IsDigit) == true
)
// Skip segmented streams
// https://github.com/Tyrrrz/YoutubeExplode/issues/159
.Where(x => x
.Descendants("Initialization")
.FirstOrDefault()?
.Attribute("sourceURL")?
.Value
.Contains("sq/") != true
)
// Skip streams without codecs
.Where(x => !string.IsNullOrWhiteSpace(x.Attribute("codecs")?.Value))
.Select(x => new StreamData(x))
.ToArray()
);
[Lazy]
public IReadOnlyList<IStreamData> Streams => _content
.Descendants("Representation")
// Skip non-media representations (like "rawcc")
// https://github.com/Tyrrrz/YoutubeExplode/issues/546
.Where(x => x
.Attribute("id")?
.Value
.All(char.IsDigit) == true
)
// Skip segmented streams
// https://github.com/Tyrrrz/YoutubeExplode/issues/159
.Where(x => x
.Descendants("Initialization")
.FirstOrDefault()?
.Attribute("sourceURL")?
.Value
.Contains("sq/") != true
)
// Skip streams without codecs
.Where(x => !string.IsNullOrWhiteSpace(x.Attribute("codecs")?.Value))
.Select(x => new StreamData(x))
.ToArray();

public DashManifest(XElement content) => _content = content;
}
Expand All @@ -46,68 +46,58 @@ public class StreamData : IStreamData
{
private readonly XElement _content;

public int? Itag => Memo.Cache(this, () =>
(int?)_content.Attribute("id")
);
[Lazy]
public int? Itag => (int?)_content.Attribute("id");

public string? Url => Memo.Cache(this, () =>
(string?)_content.Element("BaseURL")
);
[Lazy]
public string? Url => (string?)_content.Element("BaseURL");

// DASH streams don't have signatures
public string? Signature => null;

// DASH streams don't have signatures
public string? SignatureParameter => null;

public long? ContentLength => Memo.Cache(this, () =>
[Lazy]
public long? ContentLength =>
(long?)_content.Attribute("contentLength") ??

Url?
.Pipe(s => Regex.Match(s, @"[/\?]clen[/=](\d+)").Groups[1].Value)
.NullIfWhiteSpace()?
.ParseLongOrNull()
);
.ParseLongOrNull();

public long? Bitrate => Memo.Cache(this, () =>
(long?)_content.Attribute("bandwidth")
);
[Lazy]
public long? Bitrate => (long?)_content.Attribute("bandwidth");

public string? Container => Memo.Cache(this, () =>
Url?
.Pipe(s => Regex.Match(s, @"mime[/=]\w*%2F([\w\d]*)").Groups[1].Value)
.Pipe(WebUtility.UrlDecode)
);

private bool IsAudioOnly => Memo.Cache(this, () =>
_content.Element("AudioChannelConfiguration") is not null
);

public string? AudioCodec => Memo.Cache(this, () =>
IsAudioOnly
? (string?)_content.Attribute("codecs")
: null
);

public string? VideoCodec => Memo.Cache(this, () =>
IsAudioOnly
? null
: (string?)_content.Attribute("codecs")
);
[Lazy]
public string? Container => Url?
.Pipe(s => Regex.Match(s, @"mime[/=]\w*%2F([\w\d]*)").Groups[1].Value)
.Pipe(WebUtility.UrlDecode);

[Lazy]
private bool IsAudioOnly => _content.Element("AudioChannelConfiguration") is not null;

[Lazy]
public string? AudioCodec => IsAudioOnly
? (string?)_content.Attribute("codecs")
: null;

[Lazy]
public string? VideoCodec => IsAudioOnly
? null
: (string?)_content.Attribute("codecs");

public string? VideoQualityLabel => null;

public int? VideoWidth => Memo.Cache(this, () =>
(int?)_content.Attribute("width")
);
[Lazy]
public int? VideoWidth => (int?)_content.Attribute("width");

public int? VideoHeight => Memo.Cache(this, () =>
(int?)_content.Attribute("height")
);
[Lazy]
public int? VideoHeight => (int?)_content.Attribute("height");

public int? VideoFramerate => Memo.Cache(this, () =>
(int?)_content.Attribute("frameRate")
);
[Lazy]
public int? VideoFramerate => (int?)_content.Attribute("frameRate");

public StreamData(XElement content) => _content = content;
}
Expand Down
Loading

0 comments on commit 9d31e97

Please sign in to comment.